Access to type T properties of IEnumerable retu

2019-06-23 16:52发布

问题:

I have a .dll and a console app that uses the said .dll but doesn't reference directly, it loads it via reflection. The console app calls a method of a class inside the .dll.
The method signature is IEnumerable<Customer> GetAll();

In the .dll I have done this:

class CustomerRepository : ICustomerRepository
{
    public IEnumerable<Customer> GetAll()
    {
        using (var db = new DB02Context())
        {
            List<Customer> list = new List<Customer>();

            // some queries to fill the list

            return list;
        }
    }
}

In the Console app I've done this:

Assembly assembly = Assembly.LoadFrom(pathToMyDLL);
Type t = assembly.GetType("MyDLL.Models.CustomerRepository");

var methodInfo = t.GetMethod("GetAll");

if(methodInfo == null)
    throw new Exception("The method doesn't exists");

var customerRepository = Activator.CreateInstance(t);

// Invoke the GetAll() method
var customerList = methodInfo.Invoke(customerRepository, null);

Now the question is, since GetAll returns IEnumerable<Customer> and my console app doesn't "know" anything about MyDLL.dll (I don't reference it directly, so it doesn't knows the Customer type).

How can I access to the Customer list in order to access Customer'a properties without having to make a reference to the .dll explicitly?

回答1:

You have three options

  1. Move Client or move a interface Client implements to a 3rd dll that both the reflected DLL and your console app can reference.
  2. Use the dynamic keyword as the type of the object (dynamic customerList = methodInfo.Invoke(...), this is the exact situation it was invented for.
  3. Cast the return type as a plain IEnumerable and use reflection calls to call the methods in Client on the object objects the IEnumerable returns.


回答2:

As everything is inside the DLL that you load dynamically, the first and fastest thing that comes to mind is to cast the GetAll as an IEnumerable<dynamic> and use the properties accordingly.



回答3:

You will never be able to make a generic IEnumerable<'Customer> object because the runtime can not statically check the properties of the class at compile time.

I was going to post about dynamic objects, but Brizio beat me to it. One other idea which might help you.

You could make a CustomerProxy class (in the console app) which exposes the public methods of customer, and invokes the Customer objects using reflection. This has the benefit of static type checking for users of the CustomerProxy class.



回答4:

http://msdn.microsoft.com/en-us/library/vstudio/dd799517(v=vs.100).aspx or search for Covariance and Contravariance in Generics

IEnumerable<Object> customerList = methodInfo.Invoke(customerRepository, null);