Question

    

Cette question a déjà une réponse ici:

         

Étant donné les interfaces suivantes:

interface IEntity
{
    int Id{get;}
} 

interface IPerson : IEntity
{
    string Name{get;} 
    int Age{get;}
}

interface ITeacher : IPerson 
{
    string StaffId{get;}
}

interface IStudent : IPerson 
{
    string StudentId{get;}
    string Courses{get;}
}

interface IRepository
{
    T Get<T>(int id) where T : IEntity
}

Je les classes suivantes dans mon espace de noms

public class EntityBase() : IEntity
{
    int Id{get;set;}
}
public class Teacher : EntityBase, ITeacher{}
public class Sudent : EntityBase, IStudent{}

Je suis actuellement ce IRepository comme la mise en œuvre suivante:

class Repository: IRepository
{
    IDataContext Context{get;set;}

    T Get<T>(int id) where T : EntityBase
    {
        if(typeof(T) == typeof(Teacher))
            return Context.Get<ITeacher>(id);
        if(typeof(T) == typeof(Sudent))
            return Context.Get<ISudent>(id);
        throw new Exception("Unknown Interface " + typeof(T).Name);
    }
}

Y at-il un Betterway de mettre en œuvre ce? Étant donné que notre contexte n'a pas connaissance de nos types de données (enseignants, étudiants), seulement ses interfaces (ITeacher, IStudent).

quelque chose peut comme ce travail?

class Repository: IRepository
{
    T Get<T>(int id) where T : EntityBase
    {
        var MyInterface = FindInterface<T>();
        return Context.Get<MyInterface>(id);
    }
}
Était-ce utile?

La solution

Je pense que cela va faire:

class Repository: IRepository
{
    IDataContext Context{get;set;}

    T Get<T>(int id) where T : EntityBase    
    {
        string[] interfaceList = new string[] 
            { "ITeacher", "IStudent"};

        Type interfaceType = null;
        foreach (string s in interfaceList)
        {
            var types = typeof(T).FindInterfaces((x, y) => x.Name == y.ToString(), s);

            if (types.Length > 0)
                interfaceType = types[0];
        }

        if (interfaceType == null)
            throw new Exception("Unknown Interface " + typeof(T).Name);

        MethodInfo method = typeof(Context).GetMethod("Get");
        MethodInfo generic = method.MakeGenericMethod(interfaceType);

        var returnValue = generic.Invoke(Context, new object[] { id });

        return (T)Convert.ChangeType(returnValue, typeof(T));
    }
}

EDIT: Comme je ne sais pas le nom de votre espace de noms, j'ai utilisé la propriété Nom pour filtrer les interfaces. En usage réel du monde, je suggère que vous utilisez FullName juste pour être sûr, comme ceci:

...
string[] interfaceList = new string[] 
                { "MyNamespace.ITeacher", "MyNamespace.IStudent"};
...
var types = typeof(T).FindInterfaces((x, y) => x.FullName == y.ToString(), s);

Autres conseils

Je pense que vous pouvez accomplir cela à travers la réflexion en trouvant la méthode Get la classe de contexte, et en invoquant comme un appel générique pour le type fourni par l'appelant T. Je n'ai pas testé, mais le code devrait ressembler à ceci :

T Get<T>(int id) where T : EntityBase
{
    Type context = Context.GetType();

    MethodInfo getMethod = context.GetMethod("Get", BindingFlags.Public);
    MethodInfo genericGet = getMethod.MakeGenericMethod(new [] {typeof(T)});

    return (T)genericGet.Invoke(Context, new object[] { id } );
}

Il me semble que vous l'entendez l'inverse. Vous ne voulez pas passer les types d'interface à Context.Get<>, avez-vous?

// is this what you mean?
if (typeof(T) == typeof(ITeacher))
    return Context.Get<Teacher>(id);

Dans ce cas, vous aurez besoin d'utiliser MakeGenericMethod, voir

Un return Context.Get<T>(id) simple pourrait être accompli comme suit:

class Repository : IRepository
{
   public IDataContext Context { get; set; }



   public T Get<T>(int id) where T : IEntity, new()
  {



      return Context.Get<T>(id);



  }
}

suivant est votre objet / modèle d'interface avec la mise en œuvre du contexte

 interface IEntity
{
    int Id{get;}
} 

interface IPerson : IEntity
{

}

interface ITeacher : IPerson 
{

}

interface IStudent : IPerson 
{

}

interface IDataContext
{
    T Get<T>(int id) where T:new();

}

interface IRepository  
{
    T Get<T>(int id) where T : IEntity , new() ;
}


public class EntityBase : IEntity
{
   public virtual int Id{get;set;}
}


public class Teacher : EntityBase, ITeacher {

    int id=0;
    public override int Id { 

                    get { return this.id; }

                    set { this.id = value; } 


                 }

}
public class Student : EntityBase, IStudent 
{
    int id=0;
    public override int Id {

                    get { return this.id; }

                    set { this.id = value; } 
                  }

}




class Context<T>: IDataContext where T: EntityBase,  new() 
{
    ArrayList store;


    public Context(int dataSize) 
    {
         store = new ArrayList(dataSize);

        for (int i = 0; i < dataSize; i++)
        {

            T t = new T();
            t.Id = i;           
            store.Add(t);


        }

    }    

    public T Get<T>(int i) where T:new()
    {
        if (i<store.Count)
        {   

            return (T)store[i]; 
        }

        else
        {
            return default(T);
        }

    }


}

Maintenant, enfin, la classe principale méthode pour démontrer que tout se tient bien.

 using System;
 using System.Collections;

class MyClass
{

    static void Main(string[] args)
    {



        Context<Teacher> teachersContext  = new Context<Teacher>(100);//contructs a db of 100 teachers
        Context<Student> studentsContext = new Context<Student>(100);//contructs a db of 100 teachers 

        Repository repo = new Repository();




        // set the repository context and get a teacher

        repo.Context = teachersContext;
        Teacher teacher1 = repo.Get<Teacher>(83); //get teacher number 83
        Console.WriteLine("Teacher Id:{0} ", teacher1.Id);



        // redirect the repositry context and now get a student

        repo.Context = studentsContext;
        Student student1 = repo.Get<Student>(35); //get student  number 35

        Console.WriteLine("Student Id: {0} ", student1.Id);



        Console.ReadLine();

    }
scroll top