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.
Related
I'm trying to wrap a COM API so that others can use my wrapper without knowing anything about the wrapped API. However, I've hit a problem trying to use some of the items from the COM API.
Let's say the COM API has a method that returns an object defined within the API.
IComChildObject IComObject.GetChildObject()
If I have a reference to the dll that defines the COM API, I can easily use this as follows...
IComChildObject childObject = myComObjectInstance.GetChildObject();
The problem I have, is that I need to be able to work with the IComChildObject through the wrapper class, without referencing the COM API dll.
I tried to create an interface in my wrapper, that would accomplish this. So inside my wrapper project, I have an interface like this.
public interface ILocalChildObject : IComChildObject{}
Then I added a property to my wrapper, that I thought would allow my external code to use the IComChildObject.
public class ComWrapper
{
IComObject comObject;
public ILocalChildObject ComChildObject { get { return comObject.GetChildObject() as ILocalChildObject;}}
}
When I run the following code from my external code, the ChildObject is null
ILocalChildObject ChildObject = myComWrapper.ComChildObject;
I'm obviously doing something wrong, but I'm in over my head on this and don't even know what to search Google for.
Maybe it's not clear what I'm trying to do, or maybe I'm trying to do something strange here. I want to create a wrapper class library in such a way, that the code that uses it doesn't have to know anything about the wrapped library. I've done okay so far, up until the point where I need to use objects from the wrapped library in the external code. I could easily resolve this by referencing the wrapped library in my external project, but I'd like to avoid doing that.
Basically, I just need a way to use the IComChildObject in my external code, without adding a reference to the COM API dll.
Any help would be greatly appreciated,
If your API is based on IDispatch you could use the dynamic keyword, something like this:
dynamic childObject = GetChildObjectSomehow();
childObject.CallAnyMethod() // compile will always succeed, will be resolved at runtime (and failed if there's like a typo error)
Note dynamic is not available on .NET core for COM objects yet.
If it's not (if it's based on IUnknown), then you'll have to declare this interface either in an external dll or .tlb, or directly in your C# code, so it can be called by the .NET runtime. You don't have to use the original .dll, you can redefine the interface by yourself if needed (maybe a simplfied version). But the runtime has to know the binary layout to be able to call it.
Another way to handle this, as Hans Passant points out, is to wrap the COM API object in a class. Then you can access the properties within the object through the new object. The only downside to this approach is there's a lot of typing, as you have to recreate any properties or methods that you want to access in the COM API object.
In the wrapper project, you'll create a class that will contain the object returned from the API. This class will also have properties and methods, that allow a user to manipulate the API object through the class.
public class LocalChildObject
{
internal IComChildObject ComChildObject;
public string ChildObjectProperty { get { reutrn ComChildObject.ChildObjectProperty; } set { ComChildObject.ChildObjectProperty = value ;}}
public LocalChildObject(IComChildObject ComChildObject)
{
this.ComChildObject = ComChildObject;
}
}
In this example, ComChildObject is the object returned from the API. Then there's a property in the class ChildObjectProperty, which allows you to get or set the ChildObjectProperty of the ComChildObject.
Then in my main wrapper class, I can have a property that returns this new object (which contains the API COM object).
public class Wrapper
{
public LocalChildObject GetLocalChildObject { get { return new LocalChildObject(ComObject.GetChildComObject());}}
}
Then in the external code I can make changes to the object through the new wrapper object
LocalChildObject localObject = myWrapperInstance.GetLocalChildObject;
localObject.ChildObjectProperty = "A new string";
This method requires recreating all the properties and methods that you want to expose through the wrapper, however, it does allow the user using the wrapper to use IntelliSense.
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);
Simple factory using reflection involves storing (registering) various type names with their corresponding class type in a hash table, then using this hash table for generating objects in the factory.
interface Product
{
void foo();
}
class ProductFactory
{
HashTable m_RegisteredProducts = new HashTable();
public void registerProduct(string productID, Type p) {
m_RegisteredProducts.add(productID, p);
}
public Product createProduct(string productID){
return (Product) new m_RegisteredProducts[productID];
}
}
I'm not clear on when does the process of registering a new type happen since all types to be used are to be loaded into the hash table at runtime. Where is the call to registerProduct() to be made?
Calling registerProduct() for all different classes at a single place inside ProductFactory class doesn't make sense since it would defeat the purpose of using reflection over naive switch/case method.
If registerProduct() is called inside the class definition of all classes implementing the interface, then an instance of the class is created after/using the Factory hence will always give an error.
Your code doesn't do reflection as it's expecting an instance implementing the Product interface, not a type. You would need addProduct to take a Type instance, check if it implements the Product interface, then dynamically create instances of it in createProduct (using something like type.GetConstructor(<constructor signature>).Invoke(<arguments>);)
Here's an article I wrote a long time ago on something similar: http://blixt.org/2009/06/05/getting-types-implementing-class-or-interface
Calling registerProduct() for all different classes at a single place inside ProductFactory class doesn't make sense since it would defeat the purpose of using reflection over naive switch/case method.
Reflection is useful when extended product classes are added into a location (say a plug-ins directory). You have a list of strings to identify the supported plug-ins that can either be defined in a text file (application properties, which provides an added layer of security) or by (via reflection) scanning said plug-ins directory (less secure if someone can drop a hacked product in there). Disclaimer: I've never done this in C#, but it works well in Java. Apart from new product code and eventually modifying the properties file, there is no modification to the application code.
If registerProduct() is called inside the class definition of all classes implementing the interface, then an instance [of] the class is created after/using the Factory hence will always give an error.
I'm not sure that's always the strategy of the code in your question (where is it from?). You might want to read more about the different strategies of reflection combined with simple factory at http://www.codeproject.com/Articles/37547/Exploring-Factory-Pattern
It depends. There are different scenarios that call for different strategies.
One strategy that I saw quite often if all product types are defined in the same assembly (or a list of assemblies) you could call something like this:
var productTypes= from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetInterfaces().Contains(typeof(IProduct));
and then call registerProduct() for every element in productTypes.
I have some feature toggles that I include in my .NET application which uses StructureMap. I want to register the feature toggles for two purposes.
Display current state of all IFeatures on a diagnostic page.
Use certain instances in constructors of services that rely on given IFeature implementations
Here is my setup. What I'm wondering is, am I doing this right? Is there a better way I could be doing it?
class HotNewFeature : IFeature { ... }
class ServiceThatUsesFeature
{
public ServiceThatUsesFeature(HotNewFeature hotNewFeature) { ... }
}
// Type registry setup
For<HotNewFeature>().Singleton().Use<HotNewFeature>();
For<IFeature>().Singleton().Add(c => c.GetInstance<HotNewFeature>);
For<ServiceThatUsesFeature>().Singleton().Use<ServiceThatUsesFeature>());
// Get all instances on the diagnostics page:
IEnumerable<IFeature> features = ServiceLocator.Current.GetAllInstances<IFeature>();
I expect that on the diagnostic page, features would in this case contain an IEnumerable with a single element, the instance of HotNewFeature.
Use the Scan feature to register all types that implement IFeature. That will satisfy your first need, to display a list on the Diagnostics page.
If a service needs a specific implementation, it should declare the specific type it needs (HotNewFeature) instead of the interface (IFeature) in the constructor. You have done this correctly in your example. At that point you do not need to do anything more in StructureMap. If you request ServiceThatUsersFeature from StructureMap, and it relies on a concrete class (HotNewFeature), StructureMap will know how to instantiate that concrete class.
I'm using a 3rd party lib to do some work. I'm passing an object to the lib and it performing some actions on each property of the object. It enumerates properties using reflection. This is how it implemented and I can't change it.
I don't know which and how many properties should be processed by the lib at compile-time. This information only available at run-time. So I can't create class declaration in my source code.
It seems dynamic feature of .net4 can't help me because lib using reflection, not dynamic.
Actually I can see only two options here:
Create a huge class definition like this:
class Data
{
public object P1 {get; set;}
public object P2 {get; set;}
....
public object PN {get; set;} // N should be at least 10.000
}
Generate class definition at runtime and use CSharpCodeProvider to compile an use it.
Can you suggest me any other options?
And sadly, I can't replace this lib with another one.
Using the first approach will lead to high memory consumption. I would have chosen use TypeBuilder class to create new types at the runtime.
What you're looking for is known as a Property Bag. You may be able to implement something like this by using ICustomTypeDescriptor to expose additional metadata (assuming your library supports it).
If your consuming library is using Reflection directly (and not taking advantage of designer features like Type Descriptors) then your best bet is probably dynamic generation of a proxy wrapper with the additional properties. Castle DynamicProxy is one good way to do this.
EDIT:
Actually, I'm not sure if Castle supports adding new properties to the proxy object. You might be stuck using IL Emit directly via TypeBuilder. This is non-trivial, as you'll need to learn enough about IL Emit to generate the property accessors and there's a bit of a learning curve. That said, it's interesting and fun stuff and worth the effort if you have the time.
I guess it's about regular GUI element like Grid or PropertyGrid.
Then I would start from reflecting grid's method that accept class instance as parameter, and if it is possible fill internal Dictionary<PropertyInfo, instance> or Dictionary<Name,Value> with my own vales.
If this is impossible, instead of Emit, try to use System.CodeDom:
Link