Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create generic class which only accepts a type which has a certain property

I want to create a class "Indicator" that will accept 'Control' and set its 'Image' property.

Since Control doesn't have an Image property, I want to implement a template class ("Indicator") which will only accept classes which have this property (Image).

Is it possible?

like image 962
Amit Lipman Avatar asked Dec 29 '15 11:12

Amit Lipman


People also ask

How do I restrict a generic class in C#?

In c#, constraints are used to restrict generics to accept only the particular type of placeholders. By using where keyword, we can apply constraints on generics. In c#, you can apply multiple constraints on generic classes or methods based on your requirements.

Which is known as generic class?

Generic classes encapsulate operations that are not specific to a particular data type. The most common use for generic classes is with collections like linked lists, hash tables, stacks, queues, trees, and so on.

Where is generic type constraint?

The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function. Constraints can specify interfaces, base classes, or require a generic type to be a reference, value, or unmanaged type.


2 Answers

We could change the way how an instance of this class is created by adding a private parameterless constructor and another public ctor in which we'll do our type checks:

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;
    }
}
like image 117
Fabjan Avatar answered Oct 20 '22 09:10

Fabjan


You can use reflection to get the property of your object:

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);
    }        
}

Note that this code assumes that Image is a string (path to an image). You can change the type in accordance with your requirements. It is just an example.

like image 4
Yeldar Kurmangaliyev Avatar answered Oct 20 '22 08:10

Yeldar Kurmangaliyev