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

更新:定義したい任意のDataAccessタイプで使用できること
を覚えておいてください。IDataAccessorModel

4

4 に答える 4

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
于 2012-08-12T15:18:26.080 に答える
0

SQLDataAccessorはジェネリッククラスではありませんが、IDataAccessorModel<IPerson, IAccessType>正確に実装されるため、メソッドCreateはを返す必要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;
    }
}

Iインターフェースを制限したい場合があるので、制約Tを追加します。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正確にタイプであり、異なるパラメータでを実装しているSqlServerため、キャストが失敗する原因になります。次のような、より正確なキャストが必要になります。SQLDataAccessorIDataAccessorModel

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

Tつまり、あなたはそれを存在と呼びますSqlServer。のように宣言Tした場合IAccessTypeSQLDataAccessorそれが保証されるわけではありませIAccessTypeSqlServer。したがって、キャストエラー。(ただし、おそらくそれを実装しているので、それSqlServerが保証されます。)IAccessType

于 2012-08-12T16:00:32.880 に答える