우리는 다음과 같은 클래스를 가지고, 이제 가정하자.리팩토링
모두를 하나의 제네릭 클래스로 변환하는 좋은 방법이 있습니까? C 번호는 일반적인 수준의 전문화에 매개 변수화 ctors를 호출 허용하지
proxy = new ProxyA(data);
때문에 (T
기준) : 핵심 문제는 라인입니다.
우리는 다음과 같은 클래스를 가지고, 이제 가정하자.리팩토링
모두를 하나의 제네릭 클래스로 변환하는 좋은 방법이 있습니까? C 번호는 일반적인 수준의 전문화에 매개 변수화 ctors를 호출 허용하지
proxy = new ProxyA(data);
때문에 (T
기준) : 핵심 문제는 라인입니다.
형식을 알고 있으면 (원하는 경우 제네릭을 사용하여) Activator.CreateInstance을 호출하여 원하는 생성자를 사용하여 해당 형식의 인스턴스를 만들 수 있습니다.
proxy = Activator.CreateInstance(typeof(TProxy), new[]{data});
이이 직접 문제를 해결할 수 있지만, 당신은 또한 ProxyA
를 전달되는 대신에 대한 DataA
을 알고하지 않습니다 ViewModelA
디자인에 대해 생각 할 수있다. 그것은 멋진 반영없이 모든 문제를 해결할 것입니다.
ProxyA를 전달하면 ProxyA의 범위가 ViewModel의 소유자로 확장되므로 캡슐화가 중단됩니다. 그게 효과가 있을지 모르지만 나는 그것을 멋진 솔루션이라고 부를 수는 없다. Activator.CreateInstance는 더 이상 보이지는 않지만 (특히 ViewModel 클래스를 몇 번만 구성하면 단 한 번 발생하므로 반사를 사용하는 데 너무 많은 시간을 낭비하지 않습니다) – Spook
리플렉션을 사용하기로 결정했습니다. 이러한 작업은 몇 번만 수행되므로 성능이 떨어지지 않고 솔루션이 나에게 충분합니다.다른 해결책은 비록 가치가있다. – Spook
public interface IDoSomething
{
void DoSth();
}
class ViewModel<T> where T : IDoSomething
{
private T proxy;
public ViewModel()
{
proxy = Activator.CreateInstance<T>();
}
//public ViewModel(T data)
//{
// proxy = data;
//}
public void DoSth()
{
proxy.DoSth();
}
public T Proxy
{
get
{
return proxy;
}
}
}
'ViewModel' 클래스의 논리가 깨졌습니다 -'Proxy'가 아닌'DoSth'를 담당합니다. 또한 간단히 :'T : BaseProxy, new()'가 필요하다면 리플렉션을 사용하지 않아도됩니다. 매개 변수없는 ctors는 일반 클래스 전문화에 호출 될 수 있습니다. – Spook
언급 한대로 리플렉션을 사용하지 않고 매개 변수화 된 생성자에서는이 작업을 수행 할 수 없습니다. 그러나이 주제에 대한 하나의 가능한 변화 :
public interface IDataProxy<T>
{
T Data { get; set; }
}
public class ViewModel<TProxy, TData>
where TProxy : class, new, IDataProxy<TData>
{
public TProxy Proxy { get; private set; }
public ViewModel(TData data)
{
Proxy = new TProxy { Data = data };
}
}
public interface IProxy
{
void DoSth();
}
public class ProxyA : IProxy
{
public ProxyA(DataA dataA)
{
}
public void DoSth()
{ }
}
public class ProxyB : IProxy
{
public ProxyB(DataB dataA)
{
}
public void DoSth()
{
}
}
public class ViewModel<T> where T : IProxy
{
private readonly IProxy _proxy;
public ViewModel(T proxy)
{
_proxy = proxy;
}
public void DoSth()
{
_proxy.DoSth();
}
}
var vm = new ViewModel<ProxyA>(new ProxyA(new DataA()));
vm.DoSth();
캡슐화를 깨는'ViewModel'의 소유자에게'Proxy'의 가시성을 확장했기 때문에 괜찮습니다. (소유자는'ViewModel'의 로컬에 대해 아무것도 알지 않아야합니다. 관련 클래스). – Spook
당신은 미리 구성된 ProxyA
또는 ProxyB
객체를 전달하여이 문제를 해결할 수 있습니다. 그 일의
한 가지 방법은 기본 생성자를 호출하기 전에 객체를 구성, 상속을 통해입니다 :
class ViewModel<TProxy, TData>
{
private TProxy proxy;
public ViewModel(TProxy proxy)
{
this.proxy = proxy;
}
public void DoSth()
{
proxy.DoSth();
}
public TProxy Proxy
{
get
{
return proxy;
}
}
}
class ViewModelA : ViewModel<ProxyA, DataA>
{
public ViewModelA(DataA data) : base(new ProxyA(data))
{
}
}
내가 DataA
및 DataB
는 생략 한 메소드 서명 어딘가에서 발생하는 여기에 가정했습니다. 그렇지 않은 경우 TData
제네릭 유형 매개 변수를 생략 할 수 있습니다.
반사는 항상 옵션이지만, 이와 같은 해결책이 허용되는 경우에는 피해야합니다.
ViewModel(TData data, Func<TData, TProxy> factory) : this(factory(data))
{
}
하는 등 사용 :
new ViewModel<ProxyA, DataA>(new DataA(), data => new ProxyA(data));
내가 잘 모르겠어요 다른 TProxy
및 TData
을위한 새로운 유형을 만들 필요가 없도록하려는 경우, 당신은 대신 두 번째 생성자를 추가 할 수 있습니다 그러나 그것은 당신의 응용 프로그램에서 할 말이 있습니다.
나는 할 수있다 : 1. 내부에서 생성 된 유일한 프록시 객체가 아니기 때문에 모든 것을 ctor에 전달해야한다. 2. 캡슐화를 깨는'ViewModel' 소유자에게'Proxy' 클래스의 범위를 확장해야합니다 (이 경우'Proxy'는 애플리케이션 로직 때문에 ViewModel의 소유자에게는 보이지 않지만 구현상의 세부 사항 때문에) . 그게 효과가 있지만 좋은 * 솔루션이라고 부를 수는 없습니다 :) – Spook
+1 공장. ViewModel (IMO) 내부에서 프록시를 전달하는 것보다 훨씬 좋은 해결책입니다. – Spook
DoSth를 변경하여 데이터 값을 가져올 수 있습니까? –
@PhillipTrelford 할 수 없습니다. 'Proxy' 객체는이 클래스 (그리고 그것을 사용하는 객체)에서 매우 중요합니다. – Spook