我正在从合同中提取依赖关系以解除依赖关系
// Abstraction -- This can be published as contract where implementation needs to implement method. Most importantly 3rd party types are not present/tied to contract
public interface ISourceFactory {
T GetSource<T>();
}
// Implementation which depends on specific source like 3rd party
public class SourceFactory {
public T GetSource<T>() //Unable to make this work
{
Type listType = typeof(T);
if (listType == typeof(SomeBase))
{
return _connection.GetSource<T>();
}
if(listType == typeof(ExternalBase)){
return _exconnection.GetSource<T>();
}
throw new Exception("Not supported");
}
private Connection _connection;
private ExternalConnection _exconnection;
}
// 3rd party implementation
public class Connection {
public T GetSource<T> where T : SomeBase
}
// 3rd party implementation
public class ExternalConnection {
public T GetSource<T> where T : ExternalBase
}
但是我无法使SourceFactory.GetSource正常工作,因为它无法将T用作通用参数。
有人可以建议解决此问题的通用方法是什么吗?
答案 0 :(得分:1)
正如评论中所说,这本身是不可能的,因为连接必须有一些共同点才能抽象为通用。您正在使用3.第三方组件,但是当您尝试在一个工厂中使用它们时,我想您想从它们中获取相同的数据。因此,我建议定义一个接口,在其中定义所需的公共部分:
public interface IConnection{
string GetConnectionString();
...
}
比起包装3d派对关系:
public class SomebaseWrapper : IConnection{
public SomebaseWrapper(SomeBase b){
}
...
}
比您要在工厂中包装的东西要多。
public interface ISourceFactory {
T GetSource<T>() where T is IConnection;
}
最后,您需要提供SomebaseWrapper并像这样实现它:
public T GetSource<T>() where T : IConnection
{
Type listType = typeof(T);
if (listType == typeof(SomebaseWrapper))
{
return new SomebaseWrapper(_connection.GetSource<SomeBase>());
}
if (listType == typeof(ExternalBaseWrapper))
{
return new (ExternalBaseWrapper)(_exconnection.GetSource<T>());
}
throw new Exception("Not supported");
}
答案 1 :(得分:0)
我正在从合同中提取依赖关系以解除依赖关系
您粘贴的代码甚至没有编译,我指的不是Generic T
,但是SomeBase
和ExternalBase
是类,其语法不正确。至少未查询的部分应采用可编译的形式
以下是使用您的代码的有效版本,并做了少量补充,以确保我们可以使用通用版本和约束:
public interface ISourceFactory
{
T GetSource<T>() where T:IBase;
}
public class SourceFactory : ISourceFactory
{
public T GetSource<T>() where T:IBase
{
Type listType = typeof(T);
if (listType.IsAssignableFrom(typeof(SomeBase)))
{
return _connection.GetSource<T>();
}
if (listType.IsAssignableFrom(typeof(ExternalBase)))
{
return _exconnection.GetSource<T>();
}
throw new Exception("Not supported");
}
private Connection _connection;
private ExternalConnection _exconnection;
}
// 3rd party implementation
public class Connection
{
public T GetSource<T>() where T : IBase
{
return default(T);
}
}
// 3rd party implementation
public class ExternalConnection
{
public T GetSource<T>() where T : IBase
{
return default(T);
}
}
public interface IBase {}
public class SomeBase : IBase {}
public class ExternalBase : IBase {}
修改:
IBase
,可以将其用作通用约束来编译代码建议的设计,以下是我希望的设计
// Source Factory Interface
public interface ISourceFactory<T>
where T:IBase
{
ISourceFactory<T> GetSource();
}
// Implementation which depends on specific source like 3rd party
public class SourceFactory<T> : ISourceFactory<T>
where T:IBase
{
public ISourceFactory<T> GetSource() //Unable to make this work
{
if(connectionDictionary.ContainsKey(typeof(T)))
return connectionDictionary[typeof(T)]();
throw new Exception("Not supported");
}
private static Dictionary<Type, Func<ISourceFactory<T>>> connectionDictionary =
new Dictionary<Type, Func<ISourceFactory<T>>>()
{
[typeof(SomeBase)] = () =>
{
var _connection = new Connection<T>();
return _connection.GetSource();
},
[typeof(ExternalBase)] = () =>
{
var _exconnection = new ExternalConnection<T>();
return _exconnection.GetSource();
},
}
}
// 3rd party implementation
public class Connection<T> : ISourceFactory<T>
where T : IBase
{
public ISourceFactory<T> GetSource()
{
return new Connection<T>();
}
}
public class ExternalConnection<T> : ISourceFactory<T>
where T : IBase
{
public ISourceFactory<T> GetSource()
{
return new ExternalConnection<T>();
}
}
public interface IBase { }
public class SomeBase : IBase { }
public class ExternalBase : IBase { }
修改:
引入了重要的修改:
IBase
用作通用约束ISourceFactory<T>
用作Connection
和ExternalConnection
类的基本接口,这些类使用SourceFactory<T>
具有相同的基本接口返回Type key
的字典,其值为Func delegate
,该字典可以在执行时返回ISourceFactory<T>
的派生类型您可以根据特定的用例来改进设计
答案 2 :(得分:-1)
您必须为此使用反射。如果通过反射根本存在诸如便利之类的东西,那么最便捷的方法是使用泛型类型,即MakeGenericType
并适当地转换结果。这还有一个优点,您只需对每种类型执行一次检查。
public class SourceFactory {
private class SourceGetter<T> {
public static readonly SourceGetter<T> Instance;
static SourceGetter() {
Type listType = typeof(T);
if (listType == typeof(SomeBase))
{
Instance = (SourceGetter<T>)Activator.CreateInstance(typeof(CollectionGetter<>).MakeGenericType(listType));
}
else if(listType == typeof(ExternalBase)){
Instance = ... }
else {
Instance = new SourceGetter<T>();
}
}
public virtual T GetSource(SourceFactory sourceFactory) {
throw new Exception();
}
}
private class CollectionGetter<T> : SourceGetter<T> where T : SomeBase {
public override T GetSource(SourceFactory sourceFactory) {
return sourceFactory._connection.GetSource<T>();
}
}
...
public T GetSource<T>()
{
return SourceGetter<T>.Instance.GetSource(this);
}
private Connection _connection;
private ExternalConnection _exconnection;
}
编辑:修改了代码,使其易于扩展。