我有一系列接口定义,所有接口定义都是编译的(所以我的对象组合正确)。正如预期的那样,对象实例化。但是,当我试图从它的'基础工厂我收到以下错误:
错误:
无法转换类型的对象 ' SampleLibrary.Domain.DataAcessors.Person.SQLDataAccessor'输入 ' Common.Contracts.DataAccessors.IDataAccessorModel`2 [SampleLibrary.Contracts.Models.IPerson,SampleLibrary.Domain.DataAccessors.Types.SqlServer]'
请记住,我正在尝试将每个实例作为IDataAccessor接口返回。
CODE:
public interface IDataAccessor<I, T>
{
T AccessType { get; }
}
public interface IDataAccessorModel<I, T> : IDataAccessor<I, T>
{
I Instance { get; }
IResult<string> Get(I instance);
IResult<string> Add(I instance);
IResult<string> Update(I instance);
IResult<string> Delete(I instance);
}
public class SQLDataAccessor : IDataAccessorModel<IPerson, IAccessType>
{
internal SQLDataAccessor(IResult<string> result)
{
_connectionString = "";
_result = result;
}
private readonly string _connectionString;
private IResult<string> _result;
public IAccessType AccessType { get { return new SqlServer(); } }
public IPerson Instance { get; private set; }
public IResult<string> Add(IPerson instance)
{
Instance = instance;
return _result;
}
public IResult<string> Get(IPerson instance)
{
Instance = instance;
return _result;
}
public IResult<string> Delete(IPerson instance)
{
Instance = instance;
return _result;
}
public IResult<string> Update(IPerson instance)
{
Instance = instance;
return _result;
}
}
public class FactoryDataAccess : IFactoryDataAccess
{
internal FactoryDataAccess() { }
public IDataAccessor<I, T> Create<I, T>()
{
var model = typeof(I);
var target = typeof(T);
if (model.IsAssignableFrom(typeof(IPerson)))
{
if (target == typeof(SqlServer)) {
var accessor = new Person.SQLDataAccessor(new Result());
// This next line FAILS!
return (IDataAccessorModel<I, T>)accessor;
}
}
throw new NotSupportedException("Type " + target.FullName + " and Source " + model.FullName + " is not supported.");
}
}
更新
请记住,您希望定义的任何所需DataAccess类型都可以使用IDataAccessorModel
。
答案 0 :(得分:1)
SQLDataAccessor
实施IDataAccessorModel<IPerson, IAccessType>
,因此仅当<I, T>
为<IPerson, IAccessType>
时才有效。不能保证这一点,因为该方法是通用的,I和T可以是任何类型,因此转换失败。
当然,既然你正在检查I和T的类型,那么知道转换是有效的,但编译器没有。你可以这样欺骗它:
return (IDataAccessorModel<I, T>)(object)accessor;
但是,由于T
为SqlServer
,因此将其作为通用类型参数没有意义。由于I
必须实现IPerson
,因此应该对其进行约束。所以方法签名应该是:
public IDataAccessor<I, T> Create<T>() where T : IPerson
答案 1 :(得分:0)
SQLDataAccessor
不是通用类,但完全实现IDataAccessorModel<IPerson, IAccessType>
,因此您的方法Create
应该返回IDataAccessor<IPerson, IAccessType>
,但您可能使用其他泛型类型调用它。 / p>
将SqlDataAccessor
更改为:
public class SQLDataAccessor<I, T> : IDataAccessorModel<I, T>
{
internal SQLDataAccessor(IResult<string> result)
{
_connectionString = "";
_result = result;
}
private readonly string _connectionString;
private IResult<string> _result;
public T AccessType { get { return new SqlServer(); } }
public I Instance { get; private set; }
public IResult<string> Add(I instance)
{
Instance = instance;
return _result;
}
public IResult<string> Get(I instance)
{
Instance = instance;
return _result;
}
public IResult<string> Delete(I instance)
{
Instance = instance;
return _result;
}
public IResult<string> Update(I instance)
{
Instance = instance;
return _result;
}
}
您可能希望将I
和T
限制为接口,因此请添加where
约束:
public class SQLDataAccessor<I, T> : IDataAccessorModel<I, T>
where I : IPerson
where T : IAccessType
答案 2 :(得分:0)
您拥有它的方式,I
可以是从IPerson
派生的任何类型,而T
完全属于SqlServer
类型,这会导致转换失败,因为{ {1}}使用不同的参数实现SQLDataAccessor
。您需要更精确的演员表,例如:
IDataAccessorModel
答案 3 :(得分:0)
如果我这样声明SQLDataAccessor
,它对我有用:
public class SQLDataAccessor : IDataAccessorModel<IPerson, SqlServer>
{
...
}
你可能会这样称呼它
var factory = new FactoryDataAccess();
var da = factory.Create<IPerson, SqlServer>();
即。您通过T
SqlServer
来调用它。如果您在T
中将IAccessType
声明为SQLDataAccessor
,则无法保证IAccessType
为SqlServer
。因此铸造错误。 (但是,SqlServer
保证为IAccessType
,因为它可能会实现它。)