是否可以创建仅接受具有特定属性的类型的泛型类

时间:2015-12-29 11:03:16

标签: c# winforms generics

我想创建一个班级"指标"这将接受'控制'并设置其图像'属性。

由于Control没有Image属性,我想实现模板类("指标"),只接受具有此属性的类(图片)。

有可能吗?

3 个答案:

答案 0 :(得分:19)

我们可以通过添加私有无参数构造函数和另一个我们将进行类型检查的公共ctor来改变创建此类实例的方式:

class Indicator<T> where T : Control
{
    private T _control;

    private Indicator() 
    {
    }

    public Indicator(T control)
    {
       if(control.GetType().GetProperties().All(p => p.Name != "Image" || p.PropertyType != typeof(Image)))
       { 
          throw new ArgumentException("This type of control is not supported");
       }
       this._control = control;
    }
}

答案 1 :(得分:4)

您可以使用反射来获取对象的属性:

public class ImagePropertyModifier 
{
    private PropertyInfo GetImageProperty(object obj)
    {
        var property = obj.GetType().GetProperty("Image");

        if (property == null)
            throw new Exception("Object has no Image property.");

        if (property.PropertyType != typeof(string))
            throw new Exception("Object's Image property is not a string.");

        return property;
    }

    private static string GetImage(object obj)
    {           
        return GetImageProperty(obj).GetValue(obj, null).ToString();
    }        

    private static string SetImage(object obj, string value)
    {
        GetImageProperty(obj).SetValue(obj, value);
    }        
}

请注意,此代码假定Image是一个字符串(图像的路径)。您可以根据您的要求更改类型。这只是一个例子。

答案 2 :(得分:0)

在@ Fabjan的答案的基础上,您可以利用静态构造函数,而不是使用反射来执行每次实例化对象的实例时识别Image属性所需的类型检查仅在类型本身被实例化时执行该检查:

class Indicator<T> where T : Control
{
    static Indicator()
    {
        {
            if (typeof(T).GetProperties().All(p => p.Name != "Image" || p.PropertyType != typeof(Image)))
                throw new Exception(typeof(T).Name + " is not a supported generic type argument because it does not have an Image property");
        }
    }

    private readonly T _control;
    public Indicator(T control)
    {
        _control = control;
    } 
}