【问题标题】:Generic collection reloader通用集合重新加载器
【发布时间】:2018-07-24 14:00:04
【问题描述】:

是否可以将特定类型例如:ConcurentBag<T> 更改为 S 类型。 我想做一个通用类来加载数据并重新加载源集合(list<T>ConcurrentBag<T>,字典)

这是我的代码:

public interface IRepositoryRelouder
{
    private void ReloadData();
}
public interface IRepositoryLoader<out T> : IRepositoryRelouder
{
    IEnumerable<T> LoadData();
}
public abstract class Test<T> : IRepositoryLoader<T>
{
    protected ConcurrentBag<T> Source;
    public abstract IEnumerable<T> LoadData();

    private void void IRepositoryRelouder.Reload() => 
        Source = new ConcurrentBag<T>(LoadData());
}

我想在父类中加载和重新加载数据,并创建可以访问 Source 属性的子类。将 ConcurentBag 替换为下一个泛型参数是否可行?

我想知道是否有可能是这样的:

 public abstract class Test<T,S> : IRepositoryLoader<T>
    {
        protected S <T> Source;
        public abstract IEnumerable<T> LoadData();

        private void void IRepositoryRelouder.Reload() => 
            Source = new S <T>(LoadData());
    }

Where S is ConcurrentBag<T> or List<T>

更新

我想将重载机制分离到父类中。 我可以有两种重新加载机制:简单和复杂(在重新加载方法中调用多个方法)。孩子们的班级可以访问存储库和工厂。 有几个insert、create方法在子类中从继承类的数据源上使用linqu。复杂的机制包含额外的字段和方法,所以我不想重复代码。 在这种情况下怎么做更好? 我可以使用也实现IEnumerable的字典吗?

IRepositoryRelouder接口仅用于配置类中实现该接口的ech类调用Reload方法。

【问题讨论】:

  • 你到底想做什么?你能提供一个伪代码示例吗?
  • 我无法理解这个问题。你能重述一下吗?您的示例代码有什么问题? (除了Test.Load应该是Test.LoadData)
  • 我认为您的目标是不可能的,因为目前还不清楚。但是你不能声明两个TestA,就像那个必须是TestB。并且泛型类型不能在运行时被替换。
  • 这个问题很不清楚。从外观上看,您只是希望能够将 ConcurrentBag List 切换为 Concurrent 包,但从听起来您想要做一些完全不同的事情
  • 现在清楚了吗?

标签: c#


【解决方案1】:

很不清楚你想从这个问题中得到什么,但从它的外观来看,你需要多个可枚举类型,具体取决于你使用的类。

public abstract class Test<T, TEnumerable> : IRepositoryLoader<T>
    Where TEnumerable : IEnumerable<T>
{
    Func<IEnumerable<T>, TEnumerable> _enumerableResolver;
    public Test(Func<IEnumerable<T>, TEnumerable> enumerableResolver)
    {
         this._enumerableResolver = enumerableResolver
    }

    protected TEnumerable Source;
    public abstract IEnumerable<T> LoadData();

    private void IRepositoryRelouder.Reload() => 
        Source = this._enumerableResolver(LoadData());
}

然后你可以这样调用实例化:

public class TestA: Test<TestItem, ConcurentBag<TestItem>>
{
   public TestA() : base(x => new ConcurentBag<TestItem>(x))
   {  
   }
}

然后我什至不明白为什么首先需要第二个参数: 当你可以让你的 reload 方法抽象时

protected abstract void Reload();

然后让你的类实现它。

public class TestA: Test<TestItem>
{
    protected void Reload() => new ConcurentBag<TestItem>(LoadData())
}

【讨论】:

    【解决方案2】:

    这是可能的,但设计有点脆弱,因为它依赖于 ConcurrentBag&lt;T&gt;List&lt;T&gt; 都可以将 IEnumerable 作为构造函数参数并填充自身这一事实。如果您需要支持构造函数参数不一致的类型,我建议您使用 johnny 的答案。

    不管怎样,你只需要这样的类型约束:

    public abstract class Test<TItem,TContainer> : IRepositoryLoader<TItem> 
        where TContainer : class, IEnumerable<TItem>
    

    ReloadData() 看起来像这样:

    void IRepositoryReloader.ReloadData()
    {       
        this.Source = (TContainer)Activator.CreateInstance(typeof(TContainer), new [] { LoadData() } );
    }
    

    见我的full working example on DotNetFiddle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-05
      • 1970-01-01
      • 2013-03-03
      • 2013-06-16
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      • 2012-06-13
      相关资源
      最近更新 更多