C# cast generic T in abstract class<T> to dynamic - c#

This is what I want to do in C# (within class Helper - without generic arguments),
List<AbstractClass<dynamic>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<dynamic>) thing);
}
This helper class would take and work with AbstractClass<> objects and give back AbstractClass<> of specific generic type. AbstractClass<T> contains many functions which return T / take in T like public T Invoke().
For Helper class T cannot be known beforehand. The Add<T>(.. thing) function is not in a class of type T.
To be used like this in Helper class's functions,
foreach(var c in data.Where(x => ...))
{
// public T Invoke() { ... } function within AbstractClass<T>
var b = c.Invoke();
// logic
}
This also fails,
List<AbstractClass<object>> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add((AbstractClass<object>) thing);
}
Now I think I can have,
List<dynamic> data; // or List<object> data;
public void Add<T>(AbstractClass<T> thing)
{
this.data.Add(thing);
}
but I want the constraint that List named data has only elements of type like
ConcreteClass : AbstractClass<OtherClass>
So we would know that there is an public T Invoke() function but we do not know what it returns. This is helpful to avoid mistakes of say misspelling Invocke and only knowing at run-time.
I want to avoid casting to dynamic every time to invoke functions that give back generic type T

To do what you want to do you are going to need to use a Contravariant interface
public class Program
{
static void Main()
{
var m = new Helper();
m.Add(new ConcreteClass());
m.Process();
}
class Helper
{
List<IAbstractClass<OtherClassBase>> data = new List<IAbstractClass<OtherClassBase>>();
public void Add(IAbstractClass<OtherClassBase> thing)
{
this.data.Add(thing);
}
public void Process()
{
foreach(var c in data.Where(x => x.ShouldBeProcessed()))
{
var b = c.Invoke();
Console.WriteLine(b.Question);
var castData = b as OtherClass;
if (castData != null)
Console.WriteLine(castData.Answer);
}
}
}
public interface IAbstractClass<out T>
{
bool ShouldBeProcessed();
T Invoke();
}
abstract class AbstractClass<T> : IAbstractClass<T>
{
public bool ShouldBeProcessed()
{
return true;
}
public abstract T Invoke();
}
class ConcreteClass : AbstractClass<OtherClass>
{
public override OtherClass Invoke()
{
return new OtherClass();
}
}
class OtherClassBase
{
public string Question { get { return "What is the answer to life, universe, and everything?"; } }
}
class OtherClass : OtherClassBase
{
public int Answer { get { return 42; } }
}
}
You do not need to tell Add what kind of class you are passing it, all that matters is it derives from the type specified. You could do public void Add(IAbstractClass<object> thing) and every class would work, but Invoke() would only return objects inside the foreach loop.
You need to figure out what is the most derived class you want Invoke() to return and that is what you set as the type in the list.

Maybe this will work for you:
public class Program
{
static void Main()
{
var m1 = new Helper<OtherClass>();
m1.Add(new ConcreteClass());
var m2 = new Helper<int>();
m2.Add(new ConcreteClass2());
}
class Helper<T>
{
List<AbstractClass<T>> data = new List<AbstractClass<T>>();
public void Add<T1>(T1 thing) where T1 : AbstractClass<T>
{
this.data.Add(thing);
}
}
class AbstractClass<T> { }
class OtherClass { }
class ConcreteClass : AbstractClass<OtherClass> { }
class ConcreteClass2 : AbstractClass<int> { }
}

Related

Variance for interface tree structure

I am struggling to cast in a tree hierarchy structure below is an example of the class hierarchy structure I would really appreciate if someone can point me in the right direction.
I am unable to cast
var myobj2 = (IR<JB>)JR;
Classes:
public class BASEA{ }
public class B: BASEA{ }
public class C: B{ }
public interface IR<T> { }
public abstract class JR<T> : IR<T> where T : B
{ public abstract void SetRule(); }
public class Action: JB<C>
{
public override void SetRule()
{
//Logic
}
}
public static class RuleLib
{
public static void ApplyTest<T>(T obj, IR<T> JB) where T:B
{
var myobj2 = (IR<JB>)JR; //=> does not cast!
}
}
public class Test
{
[Test]
public void demo()
{
var obj = new B();
var action = new Action();
RuleLib.ApplyRule(obj,action);
}
}
For this to work, your IRule interface needs to be covariant. The example given here shows the following covariance:
IEnumerable<Derived> d = new List<Derived>();
IEnumerable<Base> b = d;
This is basically exactly what you're doing. So in your code all you need to do is write
public interface IRule<out T> { ... }
instead of
public interface IRule<T> { ... }
This makes it so that you can cast from an IRule<U> to IRule<V> where U is a subclass of V (e.g. casting from IRule<ShiftAction> to IRule<Job>).

Get trait in subclass

I'm sorry if this is poorly worded or if this has been asked before but I couldn't seem to find anything related to this and I'm quite tired.
Alright, so what I'm trying to do is get the value of of my trait in a subclass for situations where I need to reference an instance of a subclass but I don't have the information about what trait it will be using. This is easier for me to explain in code so here's what I'm trying to do.
public class TraitUser<T>
{
public void DoThingWithT(T thing)
{
thing.ToString();
}
}
public class TraitInspector
{
public void DoThing()
{
// This is where I run into my issue,
// I need to be able to get the trait that
// an instance of the TraitUser class is using to continue.
TraitUser<> tUser = GetRandomTraitUser()/*Imagine this returns an instance of TraitUser with a random trait, this is where my issue comes in.*/;
}
}
If I understand youright, you need get information about generic type T in TraitUser instance in TrairInspector.
public interface IGetTraitInfo
{
Type GetTraitObjectType();
object GetTraitObject();
}
public class TraitUser<T> : IGetTraitInfo
{
private T _thing;
public void DoThingWithT(T thing)
{
_thing = thing;
}
public Type GetTraintObjectType()
{
return typeof(T);
}
public Type GetTraitObject()
{
return _thing;
}
}
public class TrairInspector
{
public void InspectTraitUser(IGetTraitInfo traitUser)
{
Type traitType = traitUser.GetTraintObjectType();
object data = traitUser.GetTraitObject();
}
}
I didn't understand completely but this might help you.
public interface ITrait
{
string DoSomething();
}
public class Trait<T> where T : ITrait, new()
{
public string DoSomething()
{
ITrait trait = new T();
return trait.DoSomething();
}
}
public class TraitUser : ITrait
{
public string DoThing()
{
return "return something";
}
}
public class TrairInspector
{
public void DoThing()
{
Trait<TraitUser> traitUser = new Trait<TraitUser>();
traitUser.DoSomething();
}
}

How to call a method in another class from a generic method?

Why doesn't the line marked with //Dont work in the bottom of the code compile?
I want to reuse the WriteMessage method with different Classes, I try to use generics, but I'm not sure how to use it.
class ClassOne
{
public string MethodOne()
{
return ("ClassOne");
}
public string MethodTwo()
{
return ("ClassOne -MethodTwo ");
}
}
class ClassTwo
{
public string MethodOne()
{
return ("ClassTwo");
}
public string MethodTwo()
{
return ("ClassOne -MethodTwo ");
}
}
class Program
{
private static void Main()
{
var objectOne = new ClassOne();
WriteMessage(objectOne);
var objectTwo = new ClassTwo();
WriteMessage(objectTwo);
Console.ReadKey();
}
public static void WriteMessage<T>(T objectA)
{
var text = objectA.MethodTwo(); //Dont Work
Console.WriteLine("Text:{0}", text);
}
}
Try implementing a interface :
Example :
public interface IHasTwoMethods
{
string MethodOne()
string MethodTwo()
}
Implement this inteface on your classes :
class ClassOne : IHasTwoMethods
class ClassTwo : IHasTwoMethods
Then in your generic method do like this :
public static void WriteMessage<T>(T objectA) where T : IHasTwoMethods
{
var text = objectA.MethodTwo(); //Will work
Console.WriteLine("Text:{0}", text);
}
You can read more about interfaces here : http://msdn.microsoft.com/en-us/library/87d83y5b.aspx
This doesn't compile because as far as the compiler is concerned objectA is just an Object.
To get this to work, you need to use a generic type constraint:
public interface MyInterface
{
string MethodTwo();
}
public class A : MyInterface
{
...
}
public class B : MyInterface
{
...
}
public static void WriteMessage<T>(T objectA) where T: MyInterface
{
var text = objectA.MethodTwo(); //Will Work!
Console.WriteLine("Text:{0}", text);
}
MSDN : Constraints on Type Parameters
Since you're passing in a generically-typed object with T, the compiler doesn't know what class you're using--for all it knows, it could be an int or an Application or anything.
What you probably want is to have ClassOne and ClassTwo inherit from another class that has an abstract MethodTwo class that both implement. Something like...
abstract class SuperClass
{
public abstract string MethodOne();
}
class ClassOne : SuperClass
{
public override string MethodOne()
{
return ("ClassOne");
}
}
then in Main:
public static void WriteMessage<T>(T objectA) where T : SuperClass
{
var text = objectA.MethodOne();
Console.WriteLine("Text:{0}", text);
}
Read up on C# inheritance here: http://msdn.microsoft.com/en-us/library/ms173149.aspx

How to create an abstract method with a parameter of type of implementing class

I have got a abstract class with an abstract method taking a parameter of the type of the implementing class. I can achieve this by generics like this:
abstract class Clazz<T>
{
public abstract void CopyFrom(Clazz<T> source);
}
class MyClass : Clazz<MyClass>
{
public override void CopyFrom(Clazz<MyClass>)
{
// implementation
}
}
Unfortunately I need in one of the implementing classes a list of Clazz<T> elements.
So how can I achieve this?
Of cause List<Clazz<T>> does not work.
List<Clazz<MyClass>> is too restrictive.
Removing the generics and the abstract method does work (my current solution), but this way I could forget to implement the CopyFrom() method in one of the implementing classes.
Edit: Here comes a more detailed example:
I've got an abstract class:
abstract class Clazz<T>
{
public abstract void CopyFrom(Clazz<T> source);
// ...
}
And a derived class:
class MyDerivedClass : Clazz<MyDerivedClass >
{
public string Text;
private readonly List<MySubClass> _list = new List<MySubClass>();
public override void CopyFrom(MyDerivedClass source)
{
Text = source.Text;
}
private List<Clazz> GetAllItems()
{
List<Clazz> list = new List<Clazz>();
list.Add(this);
list.AddRange(_list);
}
private class MySubClass : Clazz<MySubClass>
{
public int Number;
public override void CopyFrom(MySubClass source)
{
Number = source.Number;
}
}
}
There are several other deriving classes, the GetAllItems() Method is only needed in MyDerivedClass.
would this suffice? without more details it is hard to tell.
interface ICopyMaker
{
void CopyFrom(ICopyMaker source);
}
abstract class Clazz<T> : ICopyMaker
{
public abstract void CopyFrom(Clazz<T> source);
void ICopyMaker.CopyFrom(ICopyMaker source)
{
var src = source as Clazz<T>;
if (src == null) return; // know how to copy only from the instances of the same type
CopyFrom(src);
}
}
class MyClass : Clazz<MyClass>
{
private List<ICopyMaker> _list = new List<ICopyMaker>();
public override void CopyFrom(Clazz<MyClass> c)
{
//implementation
}
}
You can make the respective method generic, too, and introduce a constraint that takes T into account. If I understand well what you want to achieve, you can do this:
abstract class Clazz<T>
{
public abstract void CopyFrom(Clazz<T> source);
public abstract void ProcessList<TDescendant>(List<TDescendant> list)
where TDescendant : Clazz<T>;
}
class MyClass : Clazz<MyClass>
{
public override void CopyFrom(Clazz<MyClass> source)
{
// implementation
}
public override void ProcessList<TDescendant>(List<TDescendant> list)
{
// implementation
}
}
You can also easily include list processing in a descendant, like this:
class MyOtherClass : Clazz<MyOtherClass>
{
public override void CopyFrom(Clazz<MyOtherClass> source)
{
// implementation
}
// this list processing is inherited
public override void ProcessList<TDescendant>(List<TDescendant> list)
{
// implementation
}
// this list processing is specific to this descendant only
public void ProcessMyClassList<TDescendant>(List<TDescendant> list)
where TDescendant : Clazz<TMyClass>
{
// implementation
}
}
Then use can declare a descendant of MyClass, which in turn is a Clazz<T>, T being MyClass:
class MyDescendant : MyClass
{
}
The following works:
List<MyDescendant> list = new List<MyDescendant>();
new MyClass().ProcessList(list);
In case of MyOtherClass, the situation is a little bit different. ProcessMyClassList accepts a list of Clazz<T> or its descendants; however, not those related to MyOtherClass but to the good-ol' MyClass. This code works:
List<MyDescendant> list = new List<MyDescendant>();
new MyOtherClass().ProcessMyClassList(list); // this works
But the following won't compile:
List<MyOtherClass> list = new List<MyOtherClass>();
new MyOtherClass().ProcessList(list); // this works
new MyOtherClass().ProcessMyClassList(list); // this doesn't
Thank's everyone for your answers, but I think I have figured out a solution I can live with:
I will remove the generics and add a typecheck, like in the solution from anikiforov:
Abstract class:
abstract class Clazz
{
public abstract void CopyFrom(Clazz source);
}
And the derived class:
class MyDerivedClass : Clazz
{
public string Text;
private List<MyNestedClass> _list;
public override void CopyFrom(Clazz source)
{
var src = source as MyDerivedClass;
if (src == null) return;
Text = src.Text;
}
public List<Clazz> GetAllItems()
{
var list = new List<Clazz>();
list.Add(this);
list.AddRange(_list);
return list;
}
class MyNestedClass : Clazz
{
public int Number;
public override void CopyFrom(Clazz source)
{
var src = source as MyNestedClass;
if (src == null) return;
Number = src.Number;
}
}
}

Inheriting an already instantiated base object

Is it possible to do something like the following:
public class ChildClass : BaseClass
{
public ChildClass(BaseClass o)
{
base = o;
}
}
Basically, I want a transparent way to wrap a base class inside of other functionality. One example I've thought of is a custom Settings Provider which transparently audits the settings passed through it.
public class SettingsAuditor : SettingsProvider
{
public SettingsAuditor(SettingsProvider o)
{
base = o;
}
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
base.SetPropertyValues(context, propvals);
}
}
Then I could do the following:
mySettingsProvider = new SettingsAuditor(mySettingsProvider);
And all changes would go through the overridden SetPropertyValues before passing to the original object.
I could use a private SettingsProvider member, but then I either cannot inherit from SettingsProvider, or have an entire SettingsProvider (base) not being used at all.
I'm using C# 4.0 and .Net 4.0.
You cannot do base = o;
What you're looking for is the Decorator Pattern), which is a way to compositionally add functionality at runtime (vs. inheritance).
Instead of trying to set the base, you just contain the inner member. As long as the wrapper implements the same interface or base class as the inner object, you can pass back the new wrapper. You can wrap as many decorators as you want.
Consider:
public interface ICar
{
void Drive();
}
public class Car : ICar
{
public void Drive()
{
Console.WriteLine("vroom");
}
}
public class BuckleUp : ICar
{
ICar car;
public BuckleUp(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("click!");
car.Drive();
}
}
public class CheckMirrors : ICar
{
ICar car;
public CheckMirrors(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("mirrors adjusted");
car.Drive();
}
}
Now consider you have a method that accepts an ICar and tells it to drive. You could give it a Car, and it would work, but you could also wrap that car in a BuckleUp and a CheckMirrors and you wouldn't have to change that method at all. You've modified functionality through composition using the Decorator Pattern.
No. This looks like it should be a Composition vs Inheritance issue. You need to evaluate whether you are a "is a" or a "has a."
A little help for your journey
This is not a complete implmentation and it could probably be done much cleaner with expression trees... but this was a quick swing at faking AOP using DynamicObject with .Net 4.0.
public class MyDynamicWrapper<T> : DynamicObject
{
public T Wrapped { get; private set; }
public Action<T> Pre { get; private set; }
public Action<T> Post { get; private set; }
public MyDynamicWrapper(T wrapped, Action<T> pre, Action<T> post)
{
this.Wrapped = wrapped;
this.Pre = pre;
this.Post = post;
}
public override bool TryGetMember(
GetMemberBinder binder,
out object result)
{
var type = typeof(T);
var method = type.GetMethod(binder.Name);
if (method != null)
{
Func<object> func = () =>
{
if (Pre != null)
Pre(Wrapped);
// support for input parameters could be added here
var ret = method.Invoke(Wrapped, null);
if (Post != null)
Post(Wrapped);
return ret;
};
result = func;
return true;
}
return base.TryGetMember(binder, out result);
}
}
public class MyDynamicWrapper
{
public static MyDynamicWrapper<T> Create<T>(
T toWrap,
Action<T> pre = null,
Action<T> post = null)
{
return new MyDynamicWrapper<T>(toWrap, pre, post);
}
}
public class MyObject
{
public void MyMethod()
{
Console.WriteLine("Do Something");
}
}
class Program
{
static void Main()
{
var myobject = new MyObject();
dynamic mydyn = MyDynamicWrapper.Create(
myobject,
p => Console.WriteLine("before"),
p => Console.WriteLine("after"));
// Note that you have no intellisence...
// but you could use the old implmentation before you
// changed to this wrapped version.
mydyn.MyMethod();
/* output below
before
Do Something
after
*/
}
}
No, but you could fake it:
public class SettingsAuditor
{
SettingsProvider #base;
public SettingsAuditor(SettingsProvider o)
{
#base = o;
}
public void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
#base.SetPropertyValues(context, propvals);
}
}
Note here, #base isn't the actual base, just a varaible named base

Categories

Resources