0

我有一系列接口定义,所有这些定义都可以编译(所以我的对象组成正确)。对象按预期实例化。但是,当我尝试从其底层工厂返回对象时,出现以下错误:

错误:

无法将“SampleLibrary.Domain.DataAcessors.Person.SQLDataAccessor”类型的对象转换为“Common.Contracts.DataAccessors.IDataAccessorModel`2[SampleLibrary.Contracts.Models.IPerson,SampleLibrary.Domain.DataAccessors.Types.SqlServer]”。

请记住,我试图将每个实例作为 IDataAccessor 接口返回。

代码:

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.");
    }
}

更新:
请记住,IDataAccessorModel您希望定义的任何所需的 DataAccess 类型都可以使用它。

4

4 回答 4

1

SQLDataAccessor工具IDataAccessorModel<IPerson, IAccessType>,所以只有<I, T><IPerson, IAccessType>. 对此无法保证,因为该方法是通用的,并且 I 和 T 可以是任何类型,所以转换失败。

当然,由于您正在检查 I 和 T 的类型,因此您知道强制转换是有效的,但编译器不会。你可以这样欺骗它:

return (IDataAccessorModel<I, T>)(object)accessor;

但是,由于T has to be SqlServer,将其设为泛型类型参数是没有意义的。并且由于I必须实施IPerson,因此应该对其进行限制。所以方法签名应该是:

public IDataAccessor<I, T> Create<T>() where T : IPerson
于 2012-08-12T15:18:26.080 回答
0

SQLDataAccessor不是泛型类,但IDataAccessorModel<IPerson, IAccessType>完全实现,所以你的方法Create应该 return IDataAccessor<IPerson, IAccessType>,但你可能用其他泛型类型调用它。

更改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;
    }
}

您可能想要限制IT到接口,所以添加一个where约束:

public class SQLDataAccessor<I, T> : IDataAccessorModel<I, T> 
    where I : IPerson
    where T : IAccessType
于 2012-08-12T15:19:21.137 回答
0

您拥有它的方式I可以是派生自任何类型IPerson并且T恰好属于 type SqlServer,这将导致强制转换失败,因为使用不同的参数SQLDataAccessor实现。IDataAccessorModel您将需要更精确的演员表,例如:

return (IDataAccessorModel<IPerson, IAccessType>)accessor;
于 2012-08-12T15:32:10.130 回答
0

如果我SQLDataAccessor 这样声明,它对我有用:

public class SQLDataAccessor : IDataAccessorModel<IPerson, SqlServer>
{
    ...
}

你可能这样称呼它

var factory = new FactoryDataAccess();
var da = factory.Create<IPerson, SqlServer>();

即你用Tbeing来称呼它SqlServer。如果您声明TIAccessTypein SQLDataAccessor,则不保证IAccessType会是SqlServer. 因此铸造错误。(但是,SqlServer保证是IAccessType因为它可能实现它。)

于 2012-08-12T16:00:32.880 回答