C# 具有从基类派生的附加属性的接口

C# 具有从基类派生的附加属性的接口,c#,inheritance,design-patterns,interface,abstract-class,C#,Inheritance,Design Patterns,Interface,Abstract Class,我尝试将一些操作提取到具有以下附加属性的接口中: 基本实体类: public enum MyClassEnum { classA, classB, classC } public abstract class MyBaseClass { public string entityA { get;set; } public int entityB { get; set; } } 然后我有一个从MyBaseClass派生的类: public class Cl

我尝试将一些操作提取到具有以下附加属性的接口中:

基本实体类:

public enum MyClassEnum
{
    classA,
    classB,
    classC
}

public abstract class MyBaseClass
{
    public string entityA { get;set; }
    public int entityB { get; set; }
}
然后我有一个从MyBaseClass派生的类:

public class ClassA : MyBaseClass{}

public class ClassB : MyBaseClass
{
    public string AnotherEntity { get; set; }
}

public class ClassC : MyBaseClass
{
    public string AnotherEntity2 { get; set; }
    public string AnotherEntity3 { get; set; }
}
我尝试有这样一个界面(这是我到目前为止得到的):

混凝土等级应该是这样的:

public class ClassBRepository : IMyClassRepository
{
    private readonly BaseRepository _baseRepository;

    public ClassBRepository
    {
        _baseRepository = new BaseRepository();
    }

    public void Create(MyBaseClass param)
    {
        // will use automapper to do the mapping
        var theClassB = MyBaseClass.TranslateTo<ClassB>();

        // How i can design the interface that accept additional Property on class B?

        // last save the operation to DB..
        _baseRepository.Save(theClassB);
    }
}
public class MyClassFactory
{
    public IMyClassRepository CreateInstance(MyClassEnum param)
    {
        switch(param)
        {
            case MyClassEnum.ClassA
            {
                return new ClassARepository;
            }

            case MyClassEnum.ClassB
            {
                return new ClassBRepository;
            }

            case MyClassEnum.ClassC
            {
                return new ClassCRepository;
            }
        }
    }
}
public class ConcreteOperationClass
{
    private IMyClassRepository _myClass;
    public ConcreteOperationClass(MyClassEnum param)
    {
        _myClass = new MyClassFactory().CreateInstance(param);
    }

    public void CreateMyClass(MyBaseClass param, // this should be a parameter class B or Class C needed)
    {
        _myClass.Create(param, // additional property for classB or classC);
    }
}
最后有这样的操作课:

public class ClassBRepository : IMyClassRepository
{
    private readonly BaseRepository _baseRepository;

    public ClassBRepository
    {
        _baseRepository = new BaseRepository();
    }

    public void Create(MyBaseClass param)
    {
        // will use automapper to do the mapping
        var theClassB = MyBaseClass.TranslateTo<ClassB>();

        // How i can design the interface that accept additional Property on class B?

        // last save the operation to DB..
        _baseRepository.Save(theClassB);
    }
}
public class MyClassFactory
{
    public IMyClassRepository CreateInstance(MyClassEnum param)
    {
        switch(param)
        {
            case MyClassEnum.ClassA
            {
                return new ClassARepository;
            }

            case MyClassEnum.ClassB
            {
                return new ClassBRepository;
            }

            case MyClassEnum.ClassC
            {
                return new ClassCRepository;
            }
        }
    }
}
public class ConcreteOperationClass
{
    private IMyClassRepository _myClass;
    public ConcreteOperationClass(MyClassEnum param)
    {
        _myClass = new MyClassFactory().CreateInstance(param);
    }

    public void CreateMyClass(MyBaseClass param, // this should be a parameter class B or Class C needed)
    {
        _myClass.Create(param, // additional property for classB or classC);
    }
}

问题是如何使用
ClassB
ClassC
中的附加属性创建
IMyClassRepository
的实现?

如果我理解正确,您是在尝试设计类似于存储库模式的东西吗?如果是这样,您可以为所有实体创建一个存储库实现。为此,您需要创建一个通用接口,该接口与实体的具体实现一起工作

public interface IMyClassRepository<T> where T : MyBaseClass
{
    T Get(int id);
    void Create(T param);
    void Update(T param);
}
公共接口IMyClassRepository,其中T:MyBaseClass
{
T Get(int-id);
无效创建(T参数);
无效更新(T参数);
}
然后为每个实体创建此存储库的实现

public ClassARepo : IMyClassRepository<ClassA>{...}
public ClassARepo:IMyClassRepository{…}
然后,您可以创建一个工厂对象,动态地为这些具体实现提供服务。类似于

var repository = RepositoryFactory.Resolve<ClassB>(); 
ClassB entity = repository.Get(234);
entity.entityA = "new value";
repository.Update(entity);
var repository=RepositoryFactory.Resolve();
ClassB entity=repository.Get(234);
entity.entityA=“新值”;
更新(实体);

如果您使用Windsor Castle这样的D/I容器,您甚至不必自己实现它,您可以通过配置文件定义实现和服务,甚至可以在不必重新编译整个应用程序的情况下交换它们。

如果它们完全不同,那么继承可能不是解决方案。
void Create(MyBaseClass参数)?你能解释一下这个方法的作用吗?(通常,
Create
会返回它刚刚创建的东西,但在您的设计中不是这样)。@JustinPihony,但它们有相同的实体,和相同的操作。@AlexeiLevenkov它应该保存一些记录。如果该方法需要一个ClassB属性,那么它将需要一个ClassB作为参数。@LadderDarat对同一个问题的回答完全相同。每次需要存储库实例时,都必须创建factory对象的实例,这很难看。至少你应该把你的
CreateInstance
方法变成一个静态方法…或者把工厂对象变成一个单例对象…或者更好地使用一个依赖注入容器,比如Windsor Castle,以避免那些永远增长的
开关
cases@reptildarat不用说,使用
enum
来确定返回的实体太无用了。泛型就是用来在运行时推断底层数据类型的。你有没有想过当你的项目中需要另一个实体时会发生什么?这意味着另一个
enum
值和另一个
switch…case
…这是一个巨大的设计问题,因为自.Net Framework 2.0以来,您有了更好的选择…generics但是,我需要为每个实体在ConcreteOperationClass上创建“create”,对吗?我的目标不仅仅是接受所有参数(classA,classB,classC)的一种方法,我不太确定这是什么意思,但温莎城堡的美妙之处在于你根本不需要创建任何东西。它解决了基于配置文件的依赖关系,DI/IoC是一个方面(因为我不能在ASMX项目上“轻松地”使用它),我明白你的观点。我可以将其提取到通用存储库模式。