5

エンティティの基本クラスがあります

public class Entity<T> where T : Entity<T>, new()
{
    public XElement ToXElement()
    {
    }
    public static T FromXElement(XElement x)
    {
    }
}

Entity<T> where T : Entity<T>静的メソッド FromXElement を厳密に型指定する必要があるため、この奇妙な構造を使用する必要があります。また、そのようなエンティティがいくつかあります

public class Category : Entity<Category>
{
}
public class Collection : Entity<Collection>
{
}

基本クラスを使用してエンティティの一般的なリストを作成するにはどうすればよいですか?

var list = new List<Entity<?>>();
list.Add(new Category());
list.Add(new Collection());
4

5 に答える 5

4

その定義ではできません。Categoryと の間に「共通の基本クラス」はありませんCollection(もちろん、以外object)。

あった場合、次のようEntity<T>に定義されているとします。

public class Entity
{
}

public class Entity<T> : Entity where T : Entity<T>, new()
{
    public XElement ToXElement()
    {
    }
    public static T FromXElement(XElement x)
    {
    }
}

その後、あなたはすることができます

var list = new List<Entity>();
list.Add(new Category());
list.Add(new Collection());

しかし、それはあなたに何を買うでしょうか?

于 2012-10-10T19:40:58.710 に答える
1

abstractにマーカーがないことから、/はリフレクションを使用し、のサブタイプに対して機能するはずだEntityと思います。次のようにクラスを構成することをお勧めします。ToFromXElementEntity

public class Entity
{
    public XElement ToXElement() { ... }

    protected static T FromXElement<T>(XElement x)
        where T : Entity
    {
        ...
    }
}

public class Category : Entity
{
    public static Category : FromXElement(XElement x)
    {
        return FromXElement<Category>(x);
    }
}

「ボイラープレート」は最小限であり、型システムを創造的に回避する必要はありません。共通ベースの欠如や手動変換について心配する必要はありません。必要に応じて、ボイラープレートを完全に削除し、オブジェクトを次の場所から直接作成できますEntity

public class Entity
{
    public XElement ToXElement() { ... }

    public static T FromXElement<T>(XElement x)
        where T : Entity
    {
        ...
    }
}

本質的に、あなたがしているのは、C#が直接サポートしていない型クラスを実装することです。この不足を回避する方法はいくつかありますが、特に静的メソッドに関しては、通常、価値があるよりも厄介であることがわかります。C#が静的拡張メソッドをサポートしている場合、それは単純ですが、残念ながらサポートされていません。

于 2012-10-10T19:59:07.250 に答える
1

マーカー インターフェイスを作成します。

public interface IAmAGenericEntity { }

public class Entity<T> where T : IAmAGenericEntity, new()
// ...

public class Category : Entity<T>, IAmAGenericEntity
// ....

var list = new List<IAmAGenericEntity>();
// ...
于 2012-10-10T19:44:54.717 に答える
0

非ジェネリック クラスをすべてのエンティティ クラスの基本クラスとして定義できます。

public class Entity
{
}

エンティティにエンティティを継承させる

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

これで、エンティティのリストを次のように作成できます。

var list = new List<Entity>();
于 2012-10-10T19:44:40.830 に答える
0

クラスの非ジェネリック バージョンを追加することで、この問題を解決できます。

class Entity
{
  // methods

  public T As<T>() 
  { 
    if (this is T) return (T)this;
    throw new InvalidCastException();
  }
}

class Entity<T> : Entity where T : Entity<T>, new()

class Cathegory : Entity<T> {}

次に、基本クラスのリストを作成します。

var list = new List<Entity>()
list.Add(new Cathegory());

次に、「一般的な特定の」操作を呼び出したい場合は、「As」関数を呼び出すか、単にオブジェクトをキャストする必要があります。

于 2012-10-10T19:44:42.153 に答える