Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以创建仅接受具有特定属性的类型的泛型类_C#_Winforms_Generics - Fatal编程技术网

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

C# 是否可以创建仅接受具有特定属性的类型的泛型类,c#,winforms,generics,C#,Winforms,Generics,我想创建一个类“Indicator”,它将接受“Control”并设置其“Image”属性 由于控件没有图像属性,我想实现一个模板类(“指示符”),它只接受具有此属性的类(图像) 有可能吗?我们可以通过添加一个私有无参数构造函数和另一个公共构造函数来更改创建此类实例的方式,我们将在其中执行类型检查: class Indicator<T> where T : Control { private T _control; private Indicator()

我想创建一个类“Indicator”,它将接受“Control”并设置其“Image”属性

由于
控件
没有图像属性,我想实现一个模板类(“指示符”),它只接受具有此属性的类(图像)

有可能吗?

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

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;
    }
}
类别指示器,其中T:控件
{
私人T_控制;
私人指标()
{
}
公共指示器(T控制)
{
if(control.GetType().GetProperties().All(p=>p.Name!=“Image”| | p.PropertyType!=typeof(Image)))
{ 
抛出新ArgumentException(“不支持此类型的控件”);
}
这是._control=control;
}
}

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

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
是一个字符串(图像的路径)。您可以根据需要更改类型。这只是一个示例。

基于@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;
    } 
}
类别指示器,其中T:控件
{
静态指示器()
{
{
if(typeof(T).GetProperties().All(p=>p.Name!=“Image”| | p.PropertyType!=typeof(Image)))
抛出新异常(typeof(T).Name+“不是受支持的泛型类型参数,因为它没有图像属性”);
}
}
专用只读T_控件;
公共指示器(T控制)
{
_控制=控制;
} 
}

您可以使用反射来检查对象是否具有所需的属性,但您仍然可以传递任何控件实例…”“接受类型”。我建议修改标题。最好使用定义
Image
并将其应用于类的接口。如果类型是密封的或实例是在您无法控制的情况下创建的,则可能不可能。然后您可以使用
指示符,其中T:Control,IImageControl
这也适用于
控件
,只要您从中派生并实现接口(属性已经存在,所以这很好)+1.Fabjan@PatrickHofman-事实上,一个很好的解决方案现在已被编辑:)+1确实!你不想要
.Any
而不是
.All
?@TrevorPilley这个代码背后的想法是,我们只想在必要时抛出异常,但要做到这一点,我们必须确保没有满足条件的属性,要做到这一点,我们必须全部检查它们,然而,仍然可以使用
。任何
和反向条件,例如
if(!foo.Any(goodProperty))
但是
。所有的
正是我们需要的,为什么不使用它呢?在这种情况下,更重要的是taste@Fabjan您不需要类型为
Image
的名为
Image
的属性吗?您的代码是说,如果它们不是全部称为Image或不是全部类型Image throw,那么可能只有我一个人,但如果您有
if(!control.GetType().GetProperties().Any)(p=>p.Name==“Image”&&p.PropertyType==typeof(Image))的话,我会发现这一点更明显
Wow…这对我很有帮助。顺便说一句,我们可以用它来处理非属性的变量吗?是的,你也可以使用
GetField
FieldInfo
。很好,很整洁,+1。