【问题标题】:Make child objects have their own type static container使子对象拥有自己的类型静态容器
【发布时间】:2017-07-06 10:37:56
【问题描述】:

是否每个类对象都有自己的静态数据存储?

我的意思是,只是为了执行以下操作:

class Program
{
    static void Main(string[] args)
    {
        var car1 = new Car();
        car1.Save(); ////saves in its own storage
        var own1 = new Owner();
        own1.Save(); //saves in its own storage as well           
    }
}

在我尝试的代码中,我得到了这样的错误

'System.InvalidCastException`

在这个地方 var repo = (Repository<IEntity>) CurrentRepository;

出了什么问题,我该怎么办?

完整代码在这里:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            //var car1 = new Car();
            //car1.Save(); ////saves in its own storage
            //var own1 = new Owner();
            //own1.Save(); //saves in its own storage as well    var car1 = new Car();

        }
    }

    public interface IEntity
    {
        long Id { get; }
    }

    public class Owner : Entity
    {

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public Car Car { get; set; }

        public Owner(string firstName, string lastName, Car car) : base(new Owner())
        {
            FirstName = firstName;
            LastName = lastName;
            Car = car;
        }

        public Owner() : base()
        {
        }

    }

    public class Car : Entity
    {
        public string Name { get; set; }
        public int Year { get; set; }

        public Car() : base()
        {

        }

        public Car(string name, int year)
        {
            Name = name;
            Year = year;
        }
    }

    public abstract class Entity : IEntity
    {
        public long Id { get; }

        public static object CurrentRepository { get; set; }

        public Entity(Entity ent)
        {
            Type entityType = ent.GetType();
            var instance = Activator.CreateInstance(typeof(Repository<>).MakeGenericType(entityType));

            CurrentRepository = instance;

        }

        public Entity()
        {
        }

        public void Save()
        {
            var repo = (Repository<IEntity>)CurrentRepository;
            repo.Save(this);
        }

        public void Delete()
        {
            var repo = (Repository<IEntity>)CurrentRepository;
            repo.Delete(this);
        }
    }

    public interface IRepository<T> where T : IEntity
    {
        void Save(T entity);
        void Delete(T entity);
        T Find(long id);
    }

    public class Repository<T> : IRepository<T> where T : class, IEntity
    {
        protected BaseStorage<T> CustomDataStorage;

        public Repository()
        {
            CustomDataStorage = new BaseStorage<T>();
        }

        public void Save(T entity)
        {
            CustomDataStorage.Add(entity);
        }

        public void Delete(T entity)
        {
            CustomDataStorage.Remove(entity);
        }

        public T Find(long id)
        {
            throw new NotImplementedException();
        }
    }
    public class BaseStorage<T> : IStorage<T>
    {
        List<T> data = new List<T>();

        public void Add(T entity)
        {
            data.Add(entity);
        }

        public void Remove(T entity)
        {
            throw new NotImplementedException();
        }
    }

    public interface IStorage<T>
    {
        void Add(T entity);
        void Remove(T entity);
    }

}

【问题讨论】:

  • 您帖子中的代码很棒,但还不够(例如缺少BaseStorage)。查看stackoverflow.com/help/mcve。最终,您需要为我们提供足够的源代码,以便我们可以将其复制并粘贴到我们这边的应用程序中并进行调整。
  • @mjwills IEntity 在那里,就在开头
  • @mjwills 我更新了问题,我想这就是我得到的全部内容
  • @mjwills wellp,有一些拼写错误和额外的符号,抱歉。我编辑了我认为的
  • @mjwills 我在一个区域添加了整个代码,所以 ppl 复制和运行会更舒服。可以编译,我刚才试过了

标签: c# oop generics


【解决方案1】:

在我尝试的代码中,我得到了这样的错误

'System.InvalidCastException`

在这个地方 var repo = (Repository) CurrentRepository;

出了什么问题,我该怎么办?

这是因为您不能直接CurrentRepository(一种(Repository&lt;Car&gt;Repository&lt;Owner&gt;)类型转换为Repository&lt;IEntity&gt;

有关更多信息,请参阅here...


要在这里实现你想要的,你可以这样尝试:

  1. 使Entity 类泛型(Entity&lt;T&gt;) 并将泛型类型约束为IEntity
  2. 使CurrentRepository 成为Repository&lt;Entity&lt;T&gt;&gt; 的类型
  3. CurrentRepository 的静态初始化从实例构造函数移至静态构造函数。
  4. 使Entity&lt;T&gt;OwnerCar 对象子类与T 引用它自己的类型,使其成为一个自引用泛型

代码

public class Owner : Entity<Owner>
{
  ...
}

public class Car : Entity<Car>
{
  ...
}

public abstract class Entity<T> : IEntity
  where T: IEntity
{
  public long Id { get; }

  public static Repository<Entity<T>> CurrentRepository { get; set; }

  static Entity()
  {
    CurrentRepository = new Repository<Entity<T>>();
  }

  public Entity()
  {      
  }

  public void Save()
  {      
    CurrentRepository.Save(this);
  }

  public void Delete()
  {      
    CurrentRepository.Delete(this);
  }    
}

【讨论】:

  • 哦,这很简单!非常感谢
  • 非常好的解决方案!
【解决方案2】:

要考虑的一个选项是更改Entity,如下所示。

ConcurrentDictionary 是为了确保您获得每种类型的一个存储库。

public abstract class Entity : IEntity
{
    public long Id { get; }

    public static ConcurrentDictionary<Type, dynamic> CurrentRepository = new ConcurrentDictionary<Type, dynamic>();

    public Entity(Entity ent)
    {
        GetRepository(ent);
    }

    private static dynamic GetRepository(Entity ent)
    {
        Type entityType = ent.GetType();

        return CurrentRepository.GetOrAdd(entityType, type =>
        {
            var instance = Activator.CreateInstance(typeof(Repository<>).MakeGenericType(entityType));
            return instance;
        });
    }

    public Entity()
    {
    }

    public void Save()
    {
        var repo = GetRepository(this);
        repo.Save((dynamic)this);
    }

    public void Delete()
    {
        var repo = GetRepository(this);
        repo.Delete((dynamic)this);
    }
}

【讨论】:

    猜你喜欢
    • 2012-11-19
    • 2018-09-14
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    相关资源
    最近更新 更多