For my example I use Autofac (it's not necessary):
var r = builder.RegisterType<Helper>().As<IHelper>(); // usual using
What I'd like to do is to be able to register types somehow like:
string name1 = "Helper";
string name2 = "IHelper";
var r = builder.RegisterType<GetTypeFromName(name1)>().As<GetTypeFromName(name2)>();
Is it possible to do with reflection magic?
You would have to create a mechanism that would "figure out" which concrete types you want to register and how to expose them (the As part in AutoFac). Here is a sample of how you can register using System.Type so the missing part is obtaining the System.Types yourself.
// get your Type(s)
Type concreteType = typeof(Helper);
Type asType = typeof(IHelper);
// Autofac registration call
builder.RegisterType(concreteType).As(asType);
As you can see in the above code you should call the non-generic version of the RegisterType and As methods. (The generic versions really just call down to these anyways).
Generally to resolve a type name you would need to provide more information than just the class name. So I guess the answer is "not exactly".
The method for mapping a string to a type is Type.GetType, which is documented here: https://learn.microsoft.com/en-us/dotnet/api/system.type.gettype?view=netframework-4.7.2
As you can see, in a vacuum we can't say that "Helper" or "IHelper" would be sufficient. You probably could get by with a namespace-qualified class name. (The reason why Helper works in the "hard-coded" syntax, of course, is that the compiler can take advantage of using statements in deciding what Helper should mean. That option doesn't work when GetType is trying to understand a string at runtime.)
If you can provide a custom resolver, maybe you can make it work exactly as you describe.
If you're able to get te Type object for the type you want to register, you can pass it to Autofac using a different overload of the RegisterType method, like so:
var type = Assembly.LoadFrom(path).GetType(typeName);
builder.RegisterType(type);
Related
I have a class called ReportWorkflow<TReport> that calls some objects to generate a report of a specific type, the object are always called in the same sequence and the only true difference is the actual implementation of each object.
The constructor of this class looks like:
public ReportWorkflow(... , IFileNameProvider<TReport> fileNameProvider)
The ReportWorkflow<TReport> is constructed using dependency injection.
There are multiple ReportWorkflow<TReport> registered at the same time in the DI Container, like:
services.AddSingleton<IReportWorkflow, ReportWorkflow<HrReport>();
services.AddSingleton<IReportWorkflow, ReportWorkflow<AccountingReport>();
//More ReportWorkflows registrations...
To make sure that I get the correct file name provider for every ReportWorkflow<TReport> I've added the generic parameter TReport to the interface IFileNameProvider<TReport> but this interface never uses the generic parameter and it is only there to 'mark' and distinguish an implementation from another.
The interface definition is as follows
public interface IFileNameProvider<TReport> {
string GetFileName();
}
An implementation simply fills the generic parameter with the report type and it will be registered like:
services.AddSingleton<IFileNameProvider<HrReport>, HrFileNameProvider>();
services.AddSingleton<IFileNameProvider<AccountingReport>, AccountingFileNameProvider>();
This will ensure that when I will try to resolve ReportWorkflow<HrReport> I will get HrFileNameProvider and when I will try to resolve ReportWorkflow<AccountingReport> I will get AccountingFileNameProvider.
The 'type markers' HrReport or AccountingReport are actual classes used and returned by other objects and do contain some information.
Does it make sense to have interfaces that use generic parameters just as a sort of 'marker' to distinguish one implementation from another? And if yes, does this pattern have a name?
Congratulations, you may just have reinvented phantom types ;)
While it's a (quaint) thing in Haskell and other statically typed functional programming languages, the question here also implies that it may not be the most idiomatic design to apply to C#.
All that said, it seems to me that this is a workaround to make a DI Container work with the design. When a DI Container is in the way, it'd be worthwhile to consider whether it actually adds value, or if it's rather a liability.
Consider throwing away the container and instead relying on Pure DI. That could make everything simpler, and might also make the use of phantom types redundant.
My Goal:
I have a system where I would like others to be able to add a C# script that contains a specific method that I can lookup and execute from within another class at runtime.
My Approach:
I created an interface with a method so I can loop through any class that implements the interface using reflection and list them then have the method name be the same between all those classes.
I have class that has an enum of all the classes found during the lookup and the user can select between them at runtime.
I now need to be able to get the method of the selected class type and invoke it's method, the problem is I know the name of the method for certain but the type of the class is stored as a variable.
The Code:
//Pseudo code from memory:
//Possible solution 1:
Type selectedType = typeSelectedByEnum;
MethodInfo genericMethod = selectedType.GetMethod("TheInterfaceMethod").MakeGenericMethod(selectedType);
genericMethod.Invoke(selectedType, new object[0]);
//Possible solution 2: (however I would much prefer to use something avaliable prior to .NET 4.6)
Type selectedType = typeSelectedByEnum;
dynamic changedObj = Convert.ChangeType(selectedType, selectedType);//-Something here needs to implement IConvertable, how would I set this up?
changedObj.TheInterfaceMethod();
//Possible solution 3:
//Your solution??!
Any help appreciated, at this point I have tried many things and am open to just about any possible runtime alternative. I can provide more code if necessary.
Since you are using an interface to mark classes that have your method "TheInterfaceMethod", then the method must not be static. That means that you need an instance of the object in which to invoke the method on. The Activator class provides an easy way to create instances of objects, but it does require a default constructor with visibility (most likely a public constructor in your case).
I also noticed on potential issue with your example which is that you were calling "MakeGenericMethod". This is only necessary if the function has some generic type parameter that you need to define to have a meaningful function. Such as this interface:
interface IInterfaceWithGenericMethod
{
void TheInterfaceMethod<T>();
}
Here's an example using your variables:
Type selectedType = typeSelectedByEnum;
MethodInfo method = selectedType.GetMethod("TheInterfaceMethod");
object obj = Activator.CreateInstance(selectedType);
method.Invoke(obj, null);
Interestingly, once you have an instance of the object, you don't need reflection to invoke the method anymore. You can simply cast it to your interface. Let's assume your interface is called IAwesomeInterface:
Type selectedType = typeSelectedByEnum;
object obj = Activator.CreateInstance(selectedType);
IAwesomeInterface converted = obj as IAwesomeInterface;
converted.TheInterfaceMethod();
Following up on InternalsVisibleTo. I have looked at c# Instantiating Internal class with private constructor, and this has helped but I'm trying to cast the returned object as the internal type and, honestly I'm not 100% that that is possible.
I'm trying the route of Reflection to fix this issue, but I'm having a tough time trying to figure out how to instantiate an internal type with private methods using reflection. I can go as far as pulling the type and getting the constructor and creating an object.
How would I preform the cast of the object if the type I wish to cast is an internal type.?
public object InitPrivateCoreObjects(string Type)
{
Assembly Core = Assembly.Load("Stuff.Core, Version=0.3.3881.21340, Culture=neutral, PublicKeyToken=4fe470e63e2d354e");
Type TypeToReflect = Core.GetType("Stuff.Core.AssemblyWithIdentifer");
object o = Activator.CreateInstance(TypeToReflect);
MethodInfo mi = TypeToReflect.GetMethod("AssemblyWithIdentifer");
object newObject = mi.Invoke(o,null);
//alternatively
//ConstructorInfo ctor = TypeToReflect.GetConstructor(new Type[]{TypeToReflect.GetType()});
//ctor.Invoke(newObject, null);
return newObject;
}
I can get the type of the internal class,
I can call the constructor and instantiate an object of the type. However, since I don’t have any access to the internal type I can’t cast it and manipulate it from there.
I understand I can use Reflection.Emit to create a new class based on that type, but if I'm going that route then I might as well just copy the entire contents of the project I'm trying to access into my test project. This would be really wastefully and pointless and would require me to throw in stuff from other projects and creating a mess and it's absolutely not the route I want to go at this time.
I've seen examples accessing individual methods and properties but none that instantiate an entire class. I'm not 100% sure it's possible since in the order of operations reflection happens before access modifiers are looked at.
Can this be done, and if so, how?
For clairification sake I wanted to use the instantiated object for testing purposes and [Assembly:InternalsVisibleTo("")] wasn't working due to bug which I'm currently working around. See here for original question.
Given that you only know the type at execution time, there's really no such concept as "returning the object as the internal type". Think about what you'd want the method signature to look like... there's no way you could express it.
If the calling code knows about it in a strongly typed way, you should make the code generic instead:
public T InitPrivateCoreObjects<T>()
{
Type type = typeof(T);
...
return (T) newObject;
}
... but if the calling code doesn't know about it, that's not helpful to it.
If you could explain more about why you think you want this ability, we could try to suggest alteratives.
I can use Reflection.Emit to create a new class based on that type
Not really: code generated using Reflection.Emit follows the same rules as your own C#. You can't use it to bypass internal protection.
I've seen examples accessing individual methods and properties
That's what you'll need to do: use reflection to look up and invoke individual methods and properties.
A couple of alternatives:
Modify the internal class to implement some interface, and make that interface public. Call methods on the interface as normal.
Get [InternalsVisibleTo] working. This is the right way to go.
This is not really a direct answer to your question, but you may find this useful:
ExposedObject
If you don't have access to the internal type, nor does that type implement any public interface that you consider sufficient to interact with it, but you know beforehand the names and signatures of members on that type, this is probably your best choice.
I need to figure out the best way to call a statc method that I know only at runtime at runtime.
Every customer that use my software has a special method that return suctom string. I am thinking to put the method name in the config file and then call it at runtime.
Is it a good way?
Why not a custom class implementing a given interface? It should be better, IMO.
You could put the fully qualified class name in the config, and instantiate it by reflection:
Type t = Type.GetType(type_name_from_config);
IGivenInterface obj = (IGivenInterface) Activator.CreateInstance(t);
If each customer needs to provide a string that is not static and needs to be computed at run-time, then a good solution would be to define an interface such as:
public interface ICustomerInfo
{
string CustomerStringValue { get; }
}
and then ask each customer to provide write a class that implements this interface.
A good way to dynamically discover and load these classes at run-time is to use the .NET managed extensibility framework (only in .NET 4.0). Using MEF, you can automatically discover assemblies in a certain directory that contain types implementing a given interface. You can them use an 'Import' attribute and have MEF dynamically activate instances of these types at run-time and inject references to them into your object.
You can find more information about MEF here.
The magic of reflection!
using System.Reflection;
var type = typeof(YourStaticClass);
var customstring = type.InvokeMember
(
"methodname",
BindingFlags.InvokeMethod,
Type.DefaultBinder,
null,
null
);
This way you can store the method name in your preferred user store as a simple string. If it's an ASP.NET site, you can use user profiles, or otherwise use isolated storage or some user-scoped application settings.
I have two interfaces IDto1 and IDto2. IDto2 inherits IDto1. Both interfaces are for DTOs and so I wish to keep "complex" code out of their implementations - I do this by putting a single extension method Initialize in a static class for each interface.
So I end up with the following types IDto1, IDto2, IDto1Extensions, IDto2Extensions.
I wish to have the Initialize extension method on both interfaces, but for each to have a different implementation.
In client code I want to use code like this:
(dto as IDto1).Initialize();
...and I'd like the relevant extension method to be invoked based on the resolved type of the dto variable at runtime.
Is this possible in C# and if not why not?
Edit:
Sorry, of course this:
(dto as IDto1).Initialize();
...will invoke the Initialize method on the IDto1 type. I meant that the dto variable would be passed in as an argument to a method, under which circumstances I believe the method would be chosen polymorphically given the inheritance hierarchy I specified earlier.
Thanks for all your answers.
What you are trying to achieve here is some sort of polymorphysm. Extension methods are static methods. In OOP polymorphysm is applicable only for instance methods.
An option could be to switch to abstract classes.
Looking at your statement:
(dto as IDto1).Initialize();
...and I'd like the relevant extension method to be invoked based on the resolved type of the dto variable at runtime.
The "resolved type" of the thing in brackets is precisely IDto1. It cannot be anything else, so that is what the compiler will work with. Indeed variables never change type (I assume you mean the object referred to by the variable's value).
In .NET 4.0 / C# 4.0, an option here for duck-typing might be an instance method and dynamic...
((dynamic)dto).Initialize();
...but to be honest I can't see why you can't just add your Initialize method to the interface and use polymorphism, since that sounds the closest to what you are trying to describe.
What you are trying to accomplish is not possible because extension methods are resolved at compile time, while in your case the actual type of the dto variable is known only at runtime.
If you want to make your code more dynamic you can define the class that you want in configuration file and use something like this
String className = ConfigurationManager.AppSettings["Interface"].ToString();
IDto1 dto = (IDto1)Activator.CreateInstance(Type.GetType(className));
In this sample I use the first line to get's the class name.
The second line create an instance of the Object.
Guilherme Ferreira
http://guilhermeferreira.wordpress.com/
This sounds like a job for an abstract base class.