通用类型和接口

时间:2018-11-18 08:02:34

标签: c# generics interface abstract-class abstract

我正在尝试使用抽象的IRepository类型来抽象我的简单Entity<T>实体参数,以遵循DRY原理,并且不要在子类中重复Create(this)。但是我遇到了这个错误:

  

CS1503参数1:无法从“实体”转换为“ T”

IRepository.cs:

public interface IRepository<T>
{
    void Create(T entity);
    IEnumerable<T> ReadAll();
}

Entity.cs:

public abstract class Entity<T>
{
    protected IRepository<T> repository;

    public void Create()
    {
        repository.Create(this);//Error occurs here on this
    }
}

但是如果使public void Create()抽象并在子类中实现,则一切正常:

Entity.cs

public abstract class Entity<T>
{
    protected IRepository<T> repository;

    public abstract void Create();//Signature changed
}

TestEntity.cs

public class TestEntity:Entity<TestEntity>
{
    public override void Create()
    {
        repository.Create(this);
    }
}

但是显然,此方法将复制并粘贴到Entity的所有子类上。

  

为我的亲爱的朋友提供其他帮助:

public abstract class Base<T>
{
    public abstract String GetName();
    public String GetMyName()
    {
        return $"My Name is :{this.GetName()} Type:{this.GetType().ToString()} Is Base<T>:{this is Base<T>}";
    }
}

public class Sample : Base<Sample>
{
    public override string GetName()
    {
        return nameof(Sample);
    }
}

MessageBox.Show(new Sample().GetMyName());的结果将是:

  

我的名字是:样品类型:样品是基数:真

没有任何错误。

  

这是另一个基于Try的朋友的答案:

public interface IRepository<T>
{
    void Create(Entity<T> entity);
    IEnumerable<T> ReadAll();
}

public abstract class Entity<T>
{
    protected IRepository<T> repository;

    public virtual void Create()
    {
        repository.Create(this);
    }
}

public class TestEntity : Entity<TestEntity>
{
    public String Name { get; set; }
}

public class Repository<T> : IRepository<T>
{
    List<T> list = new List<T>();
    public void Create(Entity<T> entity)
    {
        list.Add(this);//Error
        list.Add(entity);//Also Error
    }

    public IEnumerable<T> ReadAll()
    {
        return list;
    }
}

5 个答案:

答案 0 :(得分:1)

问题是您的Entity类存储库声明,请尝试以下操作:

public abstract class Entity<T>
    {
        protected IRepository<Entity<T>> repository;

        public void Create()
        {
            repository.Create(this);
        }
    }

答案 1 :(得分:0)

您需要在void Create(T entity);界面中将void Create(Entity<T> entity);更改为IRepository<T>才能完成这项工作。

public interface IRepository<T>
{
    void Create(Entity<T> entity);
    IEnumerable<T> ReadAll();
}

public abstract class Entity<T>
{
    public T Value;
    protected IRepository<T> repository;

    public void Create()
    {
        repository.Create(this);
    }
}

public class TestEntity : Entity<TestEntity>
{
}

public class Repository<T> : IRepository<T>
{
    List<T> list = new List<T>();
    public void Create(Entity<T> entity)
    {
        list.Add(entity.Value);
    }

    public IEnumerable<T> ReadAll()
    {
        return list;
    }
}

答案 2 :(得分:0)

问题

您的问题源于您的IRepository类期望使用类型T,但是您正在将其传递给Entity<T>而不是T。

如果您要在T用作字符串的情况下使用此类,则最终会这样:

public interface IRepository<string>
{
    void Create(string entity);
    IEnumerable<string> ReadAll();
}

public abstract class Entity<string>
{
    protected IRepository<string> repository;

    public abstract void Create();//Signature changed
}

public abstract class Entity<string>
{
    protected IRepository<string> repository;

    public void Create()
    {
        //Here the compiler is expecting the parameter to be of type string, 
        //but you are passing a Entity<string> instead.
        //The compiler doesn't know how to cast it, so it throws an error.
        repository.Create(this);
    }
}

解决方案

如其他解决方案所述,您可以使字段存储库接受Entity<T>而不是T,这将解决该问题并确实带来更多的复杂性。

另一种解决方案是像这样修改界面的“ Create”方法:

public interface IRepository<T>
{
    void Create(Entity<T> entity);
    IEnumerable<T> ReadAll();
}

但是,这将迫使您的界面只能与Entities类一起使用。

答案 3 :(得分:0)

也许您应该在界面方法中使用Entity<T>而不是<T>

public interface IRepository<T>
{
    void Create(Entity<T> entity);
    IEnumerable<Entity<T>> ReadAll();
}

public abstract class Entity<T>
{
    protected IRepository<T> repository;

    public void Create()
    {
        repository.Create(this);
    }

    public IEnumerable<Entity<T>> ReadAll()
    {
        return repository.ReadAll();
    }
}

答案 4 :(得分:0)

Create(this)方法是可行的,这就是我的推断方式

    public interface IEntity
    {
    }

    public interface IEntity<T> : IEntity 
           where T : IEntity
    {
    }

    public class BaseEntity<T> : IEntity 
           where T : IEntity, IEntity<T> 
    {
    }

    public interface IRepository<T> 
           where T: IEntity
    {
        void Create(T entity);
        IEnumerable<T> ReadAll();
    }

    public class Entity<T> : BaseEntity<T> 
          where T: IEntity, 
                   IEntity<T>, 
                   IEquatable<Entity<T>>        
    {
        protected IRepository<IEntity> repository;

        public virtual void Create()
        {
            repository.Create(this);
        }

        public bool Equals(Entity<T> other)
        {
            throw new NotImplementedException();
        }
    }

这无疑会增加更多的复杂性,因此最好将Create(this)重构。