8

C#では、次のように書くことができますか?

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

上記の実装はコンパイルされないことは知っていますが、実際に達成しようとしているのは、未知の型にある種のジェネリックラッパーを実装することです。これにより、クライアントは、パラメーターによって提供される型を呼び出すのと同じようにラッパーを呼び出すことができます。T、のようなものを使用して呼び出す代わりにwrapper.Instance.SomeMember()

前もって感謝します!

4

2 に答える 2

5

これは不可能です。

私の意見では、ラッパーは継承を使用して実装する必要はないと思います。

たとえば、Engineクラスがあり、を実装する必要があるとしますFerrariEngine。そして、あなたはCarクラスを持っています。

あなたはそれCarが継承するべきだと言っていますFerrariEngine。それは私にはひどいようです!

結局のところ、継承を使用した依存性注入のようなことをしようとしていますが、これも正しい方法ではありません。

私の提案は、あなたの生活を楽にしようとしないことです。合理的なポイントに基づいてアーキテクチャを決定します。

アップデート

OPはいくつかのコメントで言った:

このクラスでタイプTのオブジェクトのインスタンスを管理できるようにしたいので、インスタンスを作成する必要があるときにクライアントが処理する必要はありません。

あなたが望むものを得るために奇妙なものを作る必要はありません:

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>
{
}

最後に、次のインスタンスを作成するとFerrariCar

Car<FerrariEngine> myFerrari = new FerrariCar();

開発者の介入なしに、エンジンがインスタンス化されて起動されます。

Lazy<T>基本的なジェネリック制約がどのように仕事をするかを確認してください;)

要約すれば:

  • エンジンの使用Lazy<T>は、一部のユーザーがプロパティにアクセスした場合にのみインスタンス化されEngineます。
  • 遅延ロードされたエンジンがインスタンス化されると、それ自体をFerrariEngine呼び出すパラメーターなしのコンストラクターが実装されるため、エンジンが起動します。Start()

このサンプルは、探しているものを取得し、C#を「そのまま」使用する方法を示していると思います。

于 2013-01-25T11:11:15.023 に答える
1

DynamicObjectを見て、次のようなことを行うことができます。

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();
    }
}
于 2013-01-25T11:55:18.300 に答える