Reputation: 927
I have this function:
Program A
public ICollection<ReportLocationInfo> GetAllReportsInstalled()
{
return _Reports;
}
I am calling it through reflection dynamically:
Program B
internal ICollection<Object> Scan(string path)
{
MethodInfo GetReports =
_reportFactoryType.GetMethod("GetAllReportsInstalled");
return (List<Object>)GetReports.Invoke(_reportFactory, null);
}
I am casting to List because I don't have ReportLocationInfo
at Program B, and I have my own translation function in hand. This of course doesn't work.
Any suggestions?
Upvotes: 1
Views: 1369
Reputation: 51224
A simple way would be:
private ICollection<object> ScanInternal(string path)
{
List<object> result = new List<object>();
MethodInfo GetReports =
_reportFactoryType.GetMethod("GetAllReportsInstalled");
IEnumerable reports = GetReports.Invoke(_reportFactory, null)
as IEnumerable;
if (reports != null) // or exception if null ?
{
foreach (object report in reports)
result.Add(report);
}
return result;
}
But a more appropriate way would be to create an interface in a separate shared assembly (e.g. IReportLocationInfo
), and then use this interface in both assemblies.
Consider refactoring your code a bit to achieve this, because invoking methods using Reflection on an object
instance is almost like doing plain C. You get no type safety.
So, the OOP way would be to have all interfaces in a separate assembly (referenced by both program A and program B):
public interface IReportFactory
{
IEnumerable<IReportLocationInfo> GetAllReportsInstalled();
}
public interface IReportLocationInfo
{
void SomeMethod();
}
And then implement your concrete factories inside "plug-in" assemblies (program A):
public class MyReportFactory : IReportFactory
{
// ...
}
And then cast each plugin to a IReportFactory
after loading inside program B.
Upvotes: 0
Reputation: 17152
ICollection<T>
implements System.Collections.IEnumerable
. You can cast to this interface and then use a foreach
to iterate through your objects.
MethodInfo GetReports = _reportFactoryType.GetMethod("GetAllReportsInstalled");
IEnumerable reports = (IEnumerable)GetReports.Invoke(_reportFactory, null);
foreach (object report in reports)
{
// Use reflection to read properties or add to a new List<object> if you
// need an ICollection<object>
}
Upvotes: 3
Reputation: 26782
First of all, you really don't want to do this.
If you insist, you will have to inspect the return value of your GetReports.Invoke call through reflection as well. Start with:
Object reports = GetReports.Invoke(_reportFactory, null);
Work from there, knowing that reports is actually of type ICollection<ReportLocationInfo>
Upvotes: 0
Reputation: 117240
Activator.CreateInstance(typeof(List<>).MakeGenericType(yourtype)) as IList
I am not sure what you are trying is correct. How can ReportInfo
suddenly change to ReporttLocationInfo
?
Upvotes: 0
Reputation: 83254
You won't be able to cast to the class that you haven't define in current assembly or the assemblies that the current assembly is referencing. There is just no way to workaround it; static typing is there for this reason.
You said that you want it to translate dynamically, by this I assume that you want it to be able to get the Intellisense out even though the class is not defined yet, well, that's just not possible.
Upvotes: 0