可以创建一个 List<Class<T>> 吗?

11
我有一个类
public class Setting<T>
{
    public string name { get; set; }

    public T value { get; set; }
}

现在我想创建一个包含不同类型 Setting<T>IList<Setting<T>>,例如:
List<Setting<T>> settingsList;
settingsList.Add(new Setting<int>());
settingsList.Add(new Setting<string>()); 

我尝试过 IList<Setting<T>>, 但由于编译器找不到类型 T, 所以似乎不可能实现。

我知道可以使用 object,但我希望它是强类型的。所以我的问题是是否有可能使其工作。


你的意思是,例如你有 Setting<ClassA>Setting<ClassB>,你想要一个包含这两个的列表? - BoltClock
@BoltClock编辑了我的问题,使其更加清晰。 - Tokk
5个回答

13

通常情况下,泛型类型在默认情况下不具有共同的类型或接口。

将您的Setting<T>类实现一个接口(或从一个公共类派生),并创建一个该接口(或类)的列表。

public interface ISetting { }

public class Setting<T> : ISetting
{
    // ...
}

// example usage:
IList<ISetting> list = new List<ISetting>
{
    new Setting<int> { name = "foo", value = 2 },
    new Setting<string> { name = "bar", value "baz" },
};

+1 你可以在 ISetting 中添加 public string name { get; set; },以明确表明这个公共接口只能包含在所有继承类中具有相同签名的操作。 - Daniel Earwicker

0

你必须使用一个共同的祖先类来表示你放入列表中的所有类类型。如果它应该是任意类型,你必须使用 object 来代替 T


0

你只能在类内部使用 T

class Setting<T>
{
    // T is defined here
}

不在函数外部。在外部,您需要指定具体的类型:

Settings<string> stringSettings = new Settings<string>();

或者

List<Settings<string>> list = new List<Settings<string>>();
list.Add(stringSettings);

0

你可以使用反射来实现。 我为另一个问题编写了这样的代码,但你可以使用它。

public abstract class GenericAccess
{
    public static IList<T> GetObjectListFromArray<T>(T item)
    {
        var r = new List<T>();
        var obj = typeof(T).Assembly.CreateInstance(typeof(T).FullName);
        var p = obj.GetType().GetProperty("Id", System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
        if (p != null)
        {
            p.SetValue(obj, item, null);
            var m = r.GetType().GetMethod("Add");
            m.Invoke(r, new object[] { obj });
        }
        return r;
    }
}

然后像这样调用它

    IList<int> r = GenericAccess.GetObjectListFromArray<int>(1);

-1
/// <summary>
/// 消息回调委托
/// </summary>
/// <typeparam name="T">TClass</typeparam>
/// <param name="result">返回实体</param>
/// <param name="args">内容包</param>
public delegate void CallbackHandler<in T>(T result, BasicDeliverEventArgs args);

/// <summary>
/// 注册监听程序接口
/// </summary>
public interface IRegistration
{
    /// <summary>
    /// 路由名称
    /// </summary>
    string ExchangeName { get; }

    /// <summary>
    /// 路由Key
    /// </summary>
    string RouteKey { get; }

    /// <summary>
    /// 回调操作
    /// </summary>
    /// <param name="args"></param>
    void Call(BasicDeliverEventArgs args);
}

/// <summary>
/// 注册监听程序
/// </summary>
/// <typeparam name="T"></typeparam>
public class Registration<T> : IRegistration where T : class
{
    /// <summary>
    /// 路由名称
    /// </summary>
    public string ExchangeName { get; set; }

    /// <summary>
    /// 路由Key
    /// </summary>
    public string RouteKey { get; set; }

    /// <summary>
    /// 消息处理器委托
    /// </summary>
    public CallbackHandler<T> Handler { get; set; }

    /// <summary>
    /// 接口回调操作
    /// </summary>
    /// <param name="args"></param>
    public void Call(BasicDeliverEventArgs args)
    {
        var message = Encoding.UTF8.GetString(args.Body.ToArray());
        Handler?.Invoke(JsonConvertHandler.DeserializeObject<T>(message), args);
    }
}

/// <summary>
/// 消息监听处理器
/// </summary>
public static class ListenerHandler
{
    /// <summary>
    /// 单任务锁
    /// </summary>
    private static readonly object Locker = new object();

    /// <summary>
    /// 所有注册列表
    /// </summary>
    public static List<IRegistration> Registrations { get; private set; }

    /// <summary>
    /// 单例化
    /// </summary>
    static ListenerHandler()
    {
        List<ListenerSetting> listeners = MqNoticeHandler.Setting.GetListeners();
        MqNoticeHandler.Listener(OnMessage, listeners);
    }

    /// <summary>
    /// 注册监听
    /// </summary>
    /// <param name="registration"></param>
    public static void Register(IRegistration registration)
    {
        lock (Locker)
            Registrations.Add(registration);
    }

    /// <summary>
    /// 解除注册
    /// </summary>
    /// <param name="registration"></param>
    public static void UnRegister(IRegistration registration)
    {
        lock (Locker)
            Registrations.Remove(registration);
    }

    /// <summary>
    /// 获取监听列表
    /// </summary>
    /// <param name="exchangeName"></param>
    /// <param name="routeKey"></param>
    /// <returns></returns>
    public static IEnumerable<IRegistration> GetRegistrations(string exchangeName, string routeKey)
    {
        return Registrations.Where(x => x.ExchangeName == exchangeName && x.RouteKey == routeKey);
    }

    /// <summary>
    /// 消息回调处理
    /// </summary>
    /// <param name="consumer">消费者</param>
    /// <param name="args">消息包</param>
    /// <returns></returns>
    private static MqAckResult OnMessage(EventingBasicConsumer consumer, BasicDeliverEventArgs args)
    {
        //Example Query and Call 
        Registrations.First().Call(args);

        //Return
        return new MqAckResult { Accept = true, ReQueue = false };
    }
}

2
很难弄清楚这个回答如何解决问题,特别是因为你没有解释任何东西。 - LarsTech
我的英语很差,抱歉。 - Hubble
通常情况下,您将使用传入类型,因此需要实现接口的Call方法以回调到请求方。因此,您需要首先定义一个委托来传递给请求方,并定义一个接口来规范回调操作。实现类继承该接口并实现回调方法。 - Hubble

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接