문제

내 단위 테스트에서 비정상적인 문제가 발생합니다. 내가 테스트하는 클래스는 런타임에 동적으로 종속성 속성을 생성하며 해당 종속성 속성의 유형은 상황에 따라 다를 수 있습니다. 단위 테스트를 작성하는 동안 다른 유형의 종속성 속성을 만들어야하며 기존 종속성 속성을 재정의 할 수 없기 때문에 오류가 발생합니다.

그렇다면 종속성 속성을 등록하지 않거나 기존 종속성 속성의 유형을 변경하는 방법이 있습니까?

감사!


ResistemetAdata ()를 사용하면 기본값과 같은 몇 가지 사항을 변경할 수 있으므로 도움이되지 않습니다. AppDomain 접근 방식은 좋은 생각이며 효과가 있지만 단위 테스트를 위해 정말로 탐구하고 싶었던 것보다 더 복잡해 보입니다.

나는 종속성 속성을 등록 할 수있는 방법을 찾지 못했기 때문에 문제를 피하기 위해 단위 테스트를 신중하게 재구성하고 조심스럽게 재구성했습니다. 나는 테스트 범위가 조금 줄어들고 있지만,이 문제는 실제 응용 프로그램에서는 결코 발생하지 않으며 단위 테스트 중에 만 그와 함께 살 수 있습니다.

도와 주셔서 감사합니다!

도움이 되었습니까?

해결책

어제 자신의 종속성 전문가가 수업을 작성하려고 할 때 비슷한 문제가있었습니다. 나는이 질문을 발견했고, 의존성 속성을 등록 할 수있는 실제 해결책이 없다는 것을 알았습니다. 그래서 나는 약간의 파기를했다 빨간 게이트 .NET 리플렉터 내가 무엇을 생각해 낼 수 있는지보기 위해.

보고 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 dp = 
  new DependencyProperty(name, propertyType, ownerType, 
    defaultMetadata, validateValueCallback);

defaultMetadata.Seal(dp, null);
//...Yada yada...
lock (Synchronized)
{
  PropertyFromName[key] = dp;
}

두 조각 모두 주변에 있습니다 DependencyProperty.PropertyFromName, 해시 가능. 나도 알아 차렸다 DependencyProperty.RegisteredPropertyList, an ItemStructList<DependencyProperty> 그러나 그것이 어디에 사용되는지 보지 못했습니다. 그러나 안전을 위해 가능하면 그로부터 제거하려고 노력했다고 생각했습니다.

그래서 나는 종속성 속성을 "등록"할 수있는 다음 코드로 상처를 입었습니다.

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);

나는 상속하는 사용자 정의 컨트롤을 만든 시나리오에 직면하고있었습니다. Selector 이는 두 가지 항목 소송 속성을 갖기위한 것입니다. HorizontalItemsSource 그리고 VerticalItemsSource.

ItemsControl 속성을 사용하지 않으며 사용자가 액세스 할 수 있기를 원하지 않습니다.

그래서 나는 읽었다 Statenjason의 위대한 대답, 그리고 그것은 DP를 제거하는 방법에 대한 거대한 POV를 주었다.
그러나 내 문제는 ItemsSourceProperty 회원과 ItemsSource ~처럼 Private Shadows (private new C#)에서는 사용한 이후 디자인 시간에로드 할 수 없었습니다. MyControlType.ItemsSourceProperty 그림자 변수를 참조합니다.
또한 언급 된 루프를 사용하는 경우 위의 ENSWERforeach DictionaryEntry 등), 나는 반복 중에 컬렉션이 바뀌 었다는 예외가있었습니다.

따라서 런타임에 의존성 프로퍼티가 하드 코드로 참조되는 약간 다른 접근법을 제시하고 컬렉션이 배열로 복사되어 변경되지 않도록 (vb.net, 죄송합니다) :

Dim dpType = GetType(DependencyProperty)
Dim bFlags = BindingFlags.NonPublic Or BindingFlags.Static

Dim FromName = 
  Function(name As String, ownerType As Type) DirectCast(dpType.GetMethod("FromName",
    bFlags).Invoke(Nothing, {name, ownerType}), DependencyProperty)

Dim PropertyFromName = DirectCast(dpType.GetField("PropertyFromName", bFlags).
  GetValue(Nothing), Hashtable)

Dim dp = FromName.Invoke("ItemsSource", GetType(DimensionalGrid))
Dim entries(PropertyFromName.Count - 1) As DictionaryEntry
PropertyFromName.CopyTo(entries, 0)
Dim entry = entries.Single(Function(e) e.Value Is dp)
PropertyFromName.Remove(entry.Key)

중요 사항: 위의 코드는 모두 사용자 정의 컨트롤의 공유 생성자에 둘러싸여 있으며 Selcetor의 하위 클래스가이를 제공한다는 것을 알고 있기 때문에 등록 된 상태를 확인할 필요가 없습니다. ItemsSource DP.

Contentemplate가 다른 DataTemplate으로 컨텐츠 프리 센터 컨텐츠를 변경할 때 PropertyChangedCallback이있는 종속성 전문가가있는 다른 DataTemplates가있는 ContentPresenter와 관련된 문제가있었습니다.

Usercontrols 언로드 이벤트에서 나는 다음을 호출했습니다.

BindingOperations.ClearAllBindings(this);
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Normal, new DispatcherOperationCallback(delegate { return null; }), null);

그것은 나를 위해 일했다

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top