c# - 获取 List<T> 的现有实例

标签 c# .net .net-4.5

我继承了一个臃肿的项目,它使用一个巨大的类作为内存数据库:

public class Database
{
    public class Parameter1
    {
        public string Code { get; set; }
        public string Label { get; set; }
        public List<Parameter1Value> paramValues;
    }

    public class Parameter2
    {
        public string Code { get; set; }
        public string Label { get; set; }
        public List<Parameter2Value> paramValues;
    }

    public class Parameter1Value
    {
        public string Value { get; set;}
        public Parameter parameter { get; set;}
    }

    public class Parameter2Value
    {
        public int Value { get; set;}
        public Parameter2 parameter { get; set;}
    }

    public List<Parameter1> parameter1List { get; set; }
    public List<Parameter2> parameter2List { get; set; }
}

我正在创建一个通用方法来创建 Parameter1 或 Parameter2 的实例(见下文)并将它们添加到它们各自的列表中,但我不知道如何使用这些类型从我的数据库中获取 parameter1List 或 parameter2List 实例类(class)。数据库类只包含一个列表 <T>每个定义类型的属性。这可能吗?

这是用于创建实例的通用方法:

public static Database Add<T>(this Database database, string code, string label) where T : new()
{
    T itemToCreate = (T)Activator.CreateInstance(typeof(T));
    itemToCreate.Code = code;
    itemToCreate.Label = label;
    var listForItem = database.GetList<T>; // This is the missing functionality
    listForItem.Add(itemToCreate);
    return database;
}

最佳答案

这是一个使用接口(interface)和通用约束的解决方案。

创建一个接口(interface)来表示一个泛型参数类,并根据需要向该接口(interface)添加成员:

public interface IParameter { ... }

还有一个表示参数列表的接口(interface):

public interface IParameterList<TParameter> where TParameter : IParameter
{
    List<TParameter> ParameterList { get; set; }
}

DatabaseParameter类实现这些新接口(interface):

public class Parameter1 : IParameter

public class Parameter2 : IParameter

public class Database : IParameterList<Parameter1>, IParameterList<Parameter2>
{
    List<Parameter1> IParameterList<Parameter1>.ParameterList { get => parameter1List; set => parameter1List = value; }
    List<Parameter2> IParameterList<Parameter2>.ParameterList { get => parameter2List; set => parameter2List = value; }

    ...
}

添加 where TParameter : IParameter约束你的通用参数工厂函数,并让工厂函数需要一个类型为 IParameterList<TParameter> 的参数这是 Database 的一个实例类(class)。这满足了 Database 的编译器类拥有 TParameter 的列表.现在我们只做 db.ParameterList.Add(r)将我们的新参数添加到正确的列表中。

public static TParameter CreateParameter<TParameter>(IParameterList<TParameter> db) where TParameter : IParameter, new()
{
    var r = new TParameter(); // This is the generic function you mentioned. Do stuff here to create your Parameter class.
    db.ParameterList.Add(r); // Add the newly created parameter to the correct list
    return r;
}

代码转储(完整的工作版本,在我拿起你的编辑后添加了通用工厂功能):

public class Parameter1 : IParameter
{
    public string Code { get; set; }
    public string Label { get; set; }
    public List<Parameter1Value> paramValues;
}

public class Parameter2 : IParameter
{
    public string Code { get; set; }
    public string Label { get; set; }
    public List<Parameter2Value> paramValues;
}

public class Parameter1Value
{
    public string Value { get; set; }
    public Parameter parameter { get; set; }
}

public class Parameter2Value
{
    public int Value { get; set; }
    public Parameter2 parameter { get; set; }
}

public class Database : IParameterList<Parameter1>, IParameterList<Parameter2>
{
    // Note: Setters for the List properties probably not needed here or in IParameterList as with the following code we instantiate them at class construction time and, in this MCVE at least, there are no further assignments
    public List<Parameter1> parameter1List { get; set; } = new List<Parameter1>();
    public List<Parameter2> parameter2List { get; set; } = new List<Parameter2>();

    List<Parameter1> IParameterList<Parameter1>.ParameterList { get => parameter1List; set => parameter1List = value; }
    List<Parameter2> IParameterList<Parameter2>.ParameterList { get => parameter2List; set => parameter2List = value; }

    public static TParameter Add<TParameter>(IParameterList<TParameter> db, string code, string label) where TParameter : IParameter, new()
    {
        var itemToCreate = new TParameter();
        itemToCreate.Code = code;
        itemToCreate.Label = label;
        db.ParameterList.Add(itemToCreate); // Add the newly created parameter to the correct list
        return itemToCreate;
    }
}

public interface IParameter
{
    string Code { get; set; }
    string Label { get; set; }
}

public interface IParameterList<TParameter> where TParameter : IParameter
{
    List<TParameter> ParameterList { get; set; }
}

// Testing:
void Main()
{
    var db = new Database();
    Database.Add<Parameter1>(db, "hello", "hello2");
    Database.Add<Parameter1>(db, "hello", "hello2");
    Database.Add<Parameter2>(db, "hello", "hello2");
    Console.WriteLine($"P1 count (should be 2): {db.parameter1List.Count()}; P2 count (should be 1): {db.parameter2List.Count}");
}

输出:

P1 count (should be 2): 2; P2 count (should be 1): 1

关于c# - 获取 List<T> 的现有实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48702540/

相关文章:

c# - Xamarin.iOS 上的回声消除 (AEC)

asp.net - asp .net core 3 的 Web 安全审计问题

.net - LabVIEW:如何检查引用是否已关闭?

c# - 如何在 C# 中访问 Dictionary<TKey, TValue>.Item 属性

.net - Clickonce .net 升级

c# - 在异常处理中,我们在 C# 中应用嵌套 try-catch 的次数最多

c# - 将日期时间转换为 yyyy-MM-ddT00 :00:00

.net - 如何使正则表达式操作超时以防止在 .NET 4.5 中挂起?

c# - 排序 ListView 不适用于 2 位数字 C#

C# .NET 4.5 在没有 shell32.shell() 的情况下获取快捷方式的目标