Is it possible for an object to display a type parameter interface?

In C #, you can write something like this:

public class MyClass<T> : T where T : class, new() { } 

I know that the above implementation does not compile, but what I'm actually trying to achieve is to implement some kind of common shell for an unknown type, so that the client can call the shell in the same way as it will call the type provided by to the T parameter, instead of calling it using something like wrapper.Instance.SomeMember() .

Thanks in advance!

+8
generics c # oop design-patterns
source share
2 answers

It's impossible.

In my opinion, I do not think that the shell should be implemented using inheritance.

For example, suppose we have an Engine class, and you need to implement FerrariEngine . And you have a Car class.

You say that Car should inherit FerrariEngine . It looks awful for me!

At the end of the day, you want to do something like dependency injection using inheritance, and again, this is not the right way.

My suggestion is do not try to make your life easier: decide architecture based on rational points.

UPDATE

OP said in some comment:

I want this class to manage instances of objects of type T, so that the client does not need to care when instances are needed to create.

You do not need to do weird things to get what you want:

 public interface IEngine { void Start(); } public sealed class FerrariEngine : IEngine { public FerrariEngine() { Start(); } public void Start() { } } public abstract class Car<TEngine> where TEngine: IEngine, new() { public Car() { _engine = new Lazy<TEngine>(() => new TEngine()); } private readonly Lazy<TEngine> _engine; public TEngine Engine { get { return _engine.Value; } } } public class FerrariCar : Car<FerrariEngine> { } 

Finally, if we create an instance of FerrariCar :

 Car<FerrariEngine> myFerrari = new FerrariCar(); 

The engine will be created and started without developer intervention!

Check how Lazy<T> and the main general restrictions are fulfilled by the task;)

In short:

  • Using Lazy<T> , the mechanism will be created only with some access to the Engine property.
  • When the created lazy engine starts, because FerrariEngine implements a parameterless constructor that calls Start() itself, it will start the engine.

I believe this example shows you how you can get what you are looking for and use C # "as is"!

+4
source share

You can look at DynamicObject and do something like this:

 class Foo<T> : DynamicObject { private T _instance; public Foo(T instance) { _instance = instance; } public override bool TrySetMember(SetMemberBinder binder, object value) { var member = typeof(T).GetProperty(binder.Name); if (_instance != null && member.CanWrite && value.GetType() == member.PropertyType) { member.SetValue(_instance, value, null); return true; } return false; } public override bool TryGetMember(GetMemberBinder binder, out object result) { var member = typeof(T).GetProperty(binder.Name); if (_instance != null && member.CanRead) { result = member.GetValue(_instance, null); return true; } result = null; return false; } } class Bar { public int SomeProperty { get; set; } } class Program { static void Main(string[] args) { var bar = new Bar(); dynamic thing = new Foo<Bar>(bar); thing.SomeProperty = 42; Console.WriteLine(thing.SomeProperty); Console.ReadLine(); } } 
+1
source share

All Articles