2

エンティティを含むドメイン層アセンブリがあり、エンティティ リポジトリの実装を含むデータ層アセンブリによって参照されます。ドメイン レイヤー アセンブリでは、エンティティは、ルート エンティティとサブ エンティティを持つ集合体に編成されます。サブエンティティを直接インスタンス化できないようにして、コンストラクターを内部にしました。このように、クライアントは new オペレーターを使用できませんが、強制的にファクトリーを使用する必要があります。

データ レイヤー アセンブリには、各エンティティのリポジトリがあります (それがルートまたはサブ エンティティであるという事実に関係なく)。リポジトリはジェネリックを使用して実装され、実際のエンティティまたはエンティティのリストを返すGetByIdおよびGetAllメソッドで問題が発生します。それらに新しいインスタンスを作成させるには、ジェネリックにnew() 制約を指定する必要があります。new() 制約には public パラメーターのないコンストラクターが必要なため、これはコンパイルされません。internalsVisibleTo属性を使用して、データ層アセンブリがドメイン層内部にアクセスできるようにしようとしましたが、うまくいきませんでした。

私はEFや他のORMを使用していませんが、非常に単純なマッピング ライブラリを備えたADO.NETを使用しています。

これはいくつかのサンプルコードです:

namespace DomainLayer {

    public class Entity {

        internal Entity() {
        }      

    }

}

namespace DataLayer {

    public class Repository<T> where T: new() {

        public T GetById<T>() {
            return new T();
        }

    }

}

namespace Client {

    public class AClientClass {

        public void aMethod() {
            Entity entity1 = new Entity(); // Not possible, correct
            Entity entity2 = new Repository<Entity>().GetById(10); //Not possible, how to fix it???
        }

    }

}

私が得ているコンパイルエラーは次のとおりです。

'DomainLayer.Entity' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'DataLayer.Repository<T>'    

どうもありがとう。セブ

リファクタリングされたコードの下で Ed_Chapel の提案を使用します。

namespace DomainLayer {

    public class Entity {

        internal Entity() {
        }      

    }

}

namespace DataLayer {

    public class Repository<T> {

        private Func<T> _creator;

        public Repository(Func<T> creator) {
            _creator = creator;
        }

        public T GetById(int id) {
            return _creator();
        }

    }
}

namespace DataLayer {
    public class EntityRepository : Repository<Entity> {

        public EntityRepository()
            : base(() => new Entity()) {
        }

    }
}

namespace Client {

    public class AClientClass {

        public void aMethod() {
            Entity entity1 = new Entity(); // Not possible, correct
            Entity entity2 = new EntityRepository().GetById(10); //Now working!!!
        }

    }

}

Ed_Chapelに感謝します!

4

2 に答える 2

1

Repository<T>リポジトリを介してアクセスされるすべてのタイプを必要とすることを回避するには、次のことSystem.Activatorを想定してください。

  1. コンストラクターのパラメーターが何であるかを知っています。と
  2. のすべてのコンストラクターはT同じシグネチャを持ちます。

例:

return (T)Activator.CreateInstance(typeof(T), new object[] { id, array, whatever });
于 2014-10-14T16:45:46.163 に答える