Объявление переменной без ключевого слова var делает переменную глобальной переменной.
У меня вчера была аналогичная проблема, когда я пытался протестировать мой собственный класс создания DependencyProperty. Я столкнулся с этим вопросом и заметил, что реального решения для отмены регистрации свойств зависимостей не существует. Поэтому я немного покопался, используя Red Gate .NET Reflector , чтобы увидеть, что я могу придумать.
Глядя на перегрузки DependencyProperty.Register
, все они, казалось, указывали на DependencyProperty.RegisterCommon
. Этот метод состоит из двух частей:
Первая - для проверки, зарегистрировано ли свойство
FromNameKey key = new FromNameKey(name, ownerType);
lock (Synchronized)
{
if (PropertyFromName.Contains(key))
{
throw new ArgumentException(SR.Get("PropertyAlreadyRegistered",
new object[] { name, ownerType.Name }));
}
}
Вторая, Регистрация DependencyProperty
DependencyProperty dp =
new DependencyProperty(name, propertyType, ownerType,
defaultMetadata, validateValueCallback);
defaultMetadata.Seal(dp, null);
//...Yada yada...
lock (Synchronized)
{
PropertyFromName[key] = dp;
}
Обе части сосредоточены вокруг DependencyProperty.PropertyFromName
, HashTable. Я также заметил DependencyProperty.RegisteredPropertyList
, ItemStructList
, но не видел, где это используется. Однако, в целях безопасности, я решил, что постараюсь удалить и это, если возможно.
Итак, я получил следующий код, который позволил мне «отменить регистрацию» свойства зависимости.
private void RemoveDependency(DependencyProperty prop)
{
var registeredPropertyField = typeof(DependencyProperty).
GetField("RegisteredPropertyList", BindingFlags.NonPublic | BindingFlags.Static);
object list = registeredPropertyField.GetValue(null);
var genericMeth = list.GetType().GetMethod("Remove");
try
{
genericMeth.Invoke(list, new[] { prop });
}
catch (TargetInvocationException)
{
Console.WriteLine("Does not exist in list");
}
var propertyFromNameField = typeof(DependencyProperty).
GetField("PropertyFromName", BindingFlags.NonPublic | BindingFlags.Static);
var propertyFromName = (Hashtable)propertyFromNameField.GetValue(null);
object keyToRemove = null;
foreach (DictionaryEntry item in propertyFromName)
{
if (item.Value == prop)
keyToRemove = item.Key;
}
if (keyToRemove != null)
propertyFromName.Remove(keyToRemove);
}
Он работал достаточно хорошо для мне запустить мои тесты без получения исключения «уже зарегистрировано». Однако я настоятельно рекомендую вам не использовать это в каком-либо производственном коде. Вероятно, есть причина, по которой MSFT предпочла не иметь формального способа отменить регистрацию свойства зависимости, и попытки пойти против него просто напрашиваются на проблемы.
private void RemoveDependency(DependencyProperty prop)
{
var registeredPropertyField = typeof(DependencyProperty).
GetField("RegisteredPropertyList", BindingFlags.NonPublic | BindingFlags.Static);
object list = registeredPropertyField.GetValue(null);
var genericMeth = list.GetType().GetMethod("Remove");
try
{
genericMeth.Invoke(list, new[] { prop });
}
catch (TargetInvocationException)
{
Console.WriteLine("Does not exist in list");
}
var propertyFromNameField = typeof(DependencyProperty).
GetField("PropertyFromName", BindingFlags.NonPublic | BindingFlags.Static);
var propertyFromName = (Hashtable)propertyFromNameField.GetValue(null);
object keyToRemove = null;
foreach (DictionaryEntry item in propertyFromName)
{
if (item.Value == prop)
keyToRemove = item.Key;
}
if (keyToRemove != null)
propertyFromName.Remove(keyToRemove);
}
Это сработало достаточно хорошо, чтобы я мог запускать тесты, не получая исключения «Уже зарегистрировано». Однако я настоятельно рекомендую вам не использовать это в каком-либо производственном коде. Вероятно, есть причина, по которой MSFT предпочла не иметь формального способа отменить регистрацию свойства зависимости, и попытки пойти против него просто напрашиваются на проблемы.
private void RemoveDependency(DependencyProperty prop)
{
var registeredPropertyField = typeof(DependencyProperty).
GetField("RegisteredPropertyList", BindingFlags.NonPublic | BindingFlags.Static);
object list = registeredPropertyField.GetValue(null);
var genericMeth = list.GetType().GetMethod("Remove");
try
{
genericMeth.Invoke(list, new[] { prop });
}
catch (TargetInvocationException)
{
Console.WriteLine("Does not exist in list");
}
var propertyFromNameField = typeof(DependencyProperty).
GetField("PropertyFromName", BindingFlags.NonPublic | BindingFlags.Static);
var propertyFromName = (Hashtable)propertyFromNameField.GetValue(null);
object keyToRemove = null;
foreach (DictionaryEntry item in propertyFromName)
{
if (item.Value == prop)
keyToRemove = item.Key;
}
if (keyToRemove != null)
propertyFromName.Remove(keyToRemove);
}
Это сработало достаточно хорошо, чтобы я мог запускать тесты, не получая исключения «Уже зарегистрировано». Однако я настоятельно рекомендую вам не использовать это в каком-либо производственном коде. Вероятно, есть причина, по которой MSFT предпочла не иметь формального способа отменить регистрацию свойства зависимости, и попытки пойти против него просто напрашиваются на проблемы.
Если все остальное перестало работать, можно создать новый AppDomain для каждого Теста.
Я не думаю, что можно не зарегистрировать свойство зависимости, но можно переопределить его путем переопределения метаданных как это:
MyDependencyProperty.OverrideMetadata(typeof(MyNewType),
new PropertyMetadata());
Если мы зарегистрируем имя для метки следующим образом:
Label myLabel = new Label();
this.RegisterName(myLabel.Name, myLabel);
Мы можем легко отменить регистрацию имени, используя:
this.UnregisterName(myLabel.Name);