views:

194

answers:

2

I have a class:

public class MyClass<T>
{
    public string TestProperty { get; set; }
}

and I want to create a delegate to run on instances of this class, such as:

Action<MyClass<object>> myDelegate = myclass => myclass.TestProperty = "hello";

However, the above delegate can't be invoked with anything other than a MyClass<object>, such as MyClass<DateTime> or MyClass<string>.

How can I either define the delegate, or modify the delegate so that I can execute the delegate on a MyClass<T> where T is anything which extends object?

Edit: This can wait until C# 4 if thats when this becomes possible (if so, please still tell me how) although i'd prefer to get on with it now in 3.5

Edit: I actually also have a 2nd class:

public class MyDerivedClass<T1, T2> : MyClass<T1>
{
    public int OtherProp { get; set; }
}

Ideally id like to use the following syntax to define some delegates:

CreateDelegate<MyClass<object>>(mc => mc.TestProperty = "hello");
CreateDelegate<MyDerivedClass<object, object>>(mc => mc.OtherProp = 4);

Then given an object, id like to see which delegate arguments match, and then run them

Is this possible? What alternatives do I have to create such delegates?

Thanks

+3  A: 

EDIT: After thinking about it a bit further, I don't believe C# 4 will actually help you in this case. You'd need the MyClass type itself to be variant, but it can't be because it's a class. However...

You could write a generic method to return you a specific action:

public Action<MyClass<T>> NewTestPropertyDelegate<T>()
{
    return myclass => myclass.TestProperty = "hello";
}

EDIT: I should have mentioned Andrew Hare's suggestion before - but here's another alternative using a base class instead of an interface.

public abstract class MyClass
{
    public string TestProperty { get; set; }
}

public class MyClass<T> : MyClass
{
    ...
}

Then use Action<MyClass>.

Jon Skeet
hmm thanks for the info, looks like im going to be out of luck. ive updated the question with a bit more info, think i may have slightly mislead you by oversimplifying the problem :(
Andrew Bullock
could i not use an Expression<Action<T>> instead, and then modify the expression to the correct T when it comes to apply it?
Andrew Bullock
@Andrew: Hmm... possibly. Not sure. I'll try to remember to have another look at this later on.
Jon Skeet
+3  A: 

You could create an interface to encapsulate the members of MyClass<T> that you need:

interface IFoo
{
    String TestProperty { get; set; }
}

Then change your delegate to use that interface:

Action<IFoo> myDelegate = myclass => myclass.TestProperty = "hello";

Edit: And obviously you would need to do this as well:

public class MyClass<T> : IFoo
{
    public String TestProperty { get; set; }
}
Andrew Hare
thanks for the help, see my comment @Tony and the updated question
Andrew Bullock
interfaces were the answer, just needed to stop being daft!
Andrew Bullock