In my code I have an interface - lets say its called InterfaceName and its implementation called InterfaceImpl. Now when I dynamically try to obtain the InterfaceImpl using the following code:
object obj = Activator.CreateInstance("ProjectName","ProjectName.Folder.InterfaceImpl");
InterfaceName in = (InterfaceName)obj; //Error pops up here
I get the following error
Unable to cast object of type 'System.Runtime.Remoting.ObjectHandle' to type 'ProjectName.Folder.InterfaceName'.
Any suggestions on what might be going wrong ?
If you read the documentation about the method you are calling, it returns
A handle that must be unwrapped to access the newly created instance.
Looking at the documentation of ObjectHandle, you simply call Unwrap() in order to get the instance of the type you are trying to create.
So, I guess your real issue is... Why?
This method is designed to be called in another AppDomain, and the handle returned back to the calling AppDomain, where the proxy to the instance is "unwrapped".
What? That doesn't explain why?
Only two types can cross an AppDomain barrier. Types that are serializable (of which copies are created), and types that extend MarshalByRefObject (of which proxies are created and passed). ObjectHandle extends MarshalByRefObject, and so can cross that AppDomain barrier, whereas the type which they are representing may not extend MBRO or be serializable. This method ensures you can get that type instance across the barrier, no matter what.
So, if you are just trying to instantiate a type, you might want to look at a different overload of CreateInstance. Or just unwrap the result.
var obj = Activator.CreateInstance("A","A.B.C") as ObjectHandle;
InterfaceName in = (InterfaceName)obj.Unwrap();
Related
I'm trying to make a simple addin. The developers documentation states this:
Late bind to ETABS.exe, create an instance of the ETABSObject, and get a reference to the cOAPI interface.
I'm very confused on how to late bind to an already running exe. If you could give me an example or point me in the right direction I would really appreciate it. I've been banging my head on wall for days.
Early Binding
When performing Early Binding, an object is assigned to a variable declared to be of a specific object type. Early binding objects are basically a strong type objects or static type objects. While Early Binding, methods, functions and properties which are detected and checked during compile time, perform other optimizations before an application executes. The biggest advantage of using early binding is for performance and ease of development.
Example :
System.IO.FileStream FS ;
FS = new System.IO.FileStream("C:\\temp.txt", System.IO.FileMode.Open);
Above code creates a variable FS to hold a new object and then assigns a new object to the variable. Here type is known before the variable is exercised during run-time.The FileStream is a specific object type, the instance assigned to FS is early bound.
While preforming Early Binding the compiler can ensure at compile time that the function will exist and be callable at runtime. Moreover the compiler guarantees that the function takes the exact number of arguments and that they are of the right type and can checks that the return value is of the correct type.
Late binding
By contrast, in Late binding functions, methods, variables and properties are detected and checked only at the run-time. It implies that the compiler does not know what kind of object or actual type of an object or which methods or properties an object contains until run time. The biggest advantages of Late binding is that the Objects of this type can hold references to any object, but lack many of the advantages of early-bound objects.
Example:
//The var keyword instructs the compiler to infer the type of the variable
// from the expression on the right side of the initialization statement.
var eTabsObj = null;//notice the var keyword
//instead of var you can use an interface variable to hold reference
// of late bind object
eTabsObj = CreateObject("<create an instance of ETABSObject>");//executed at runtime
Above code does not require a reference to be set beforehand, the instance creation and type determination will happen at runtime. It is important to note that the Late binding can only be used to access type members that are declared as Public. Accessing members declared as Friend or Protected Friend result in a run-time error.
To answer your specific question, you are creating an object during runtime, and it makes sense because when the author of the ETABS.exe wrote the code he didn't knew how you would like to use it in your project.You created an object in the way which suits your requirement.
Notice how we used var to hold reference to ETABS object , var is basically a syntactic sugar which infers object type from the object being assigned. Now instead of using var you could use an interface variable which ETABS class implements to hold the reference of the object.
While perform late binding there is a possibility of the target function may not exist. Also the target function may not accept the arguments passed to it, and may have a return value of the wrong type.
Hope this helps !
Say I have a method that is overloaded such as void PrintInfo(Person) and void PrintInfo(Item), and so on. I try to invoke these methods by passing in an Object.
I'm wondering why it is giving me an error when I do this; aren't all classes inherited from Object? I want to avoid doing an if/switch statement where I check which type the Object is before calling the appropriate method.
What do you guys think is the best approach in this case?
All Persons are objects , but not all objects are Persons. Because of this you can pass a Person to a method that accepts an object but you can't pass an object to a method that requires a Person.
It sounds like you have some common bit of functionality between various objects that you want to use. Given this, it would be best to find either a common ancestor that has all of the functionality that you need, or an interface that they all implement (that again provides everything that you need).
In the case of printing, you may just need the ToString method. In that case, you can just have the method accept an object and call ToString on it. (That's what many print methods do, such as Console.WriteLine.
You need to understand that because C# is a statically typed language (barring dynamic) the particular overload that is chosen (called overload resolution) is determined at compile time, not run time. That means that the compiler needs to be able to unequivocally determine what type your argument is. Consider:
Object foo;
foo = "String";
foo = 5;
PrintInfo(foo); // Which overload of printinfo should be called? The compiler doesn't know!
There are a few ways to solve this- making foo of type dynamic is one- that will cause the correct overload to be chosen at compile time. The problem with that is that you lose type safety- if you don't have an appropriate overload for that type, your application will still compile but will crash when you try to print the unsupported type's info.
An arguably better approach is to ensure that foo is always of the correct type, rather than just Object.
As #Servy suggests, another approach is to attach the behavior to the type itself. You could, for instance, make an interface IHasPrintInfo:
public interface IHasPrintInfo { String PrintInfo { get; } }
and implement that interface on all items whose info you might print. Then your PrintInfo function can just take an IPrintInfo:
public void PrintInfo(IPrintInfo info) {
Console.WriteLine(info.PrintInfo);
}
here its ambiguate for compiler; compiler can't figure out which version of method (Person/Item) you are intended to call.
In the latest version of C#, is it possible to convert a dynamic type to a strong type, if you know the type in advance?
I'm using reflection to call a method on an object, which returns to a var:
var returnVal = context.GetType().InvokeMember(MethodName, BindingFlags.InvokeMethod, null, context, lParams.ToArray());
I can easily get the type being returned to returnVal. Is it possible to cast\convert thins to a more strongly typed version?
EDIT FOR CLARITY:
In this situation, I know the type being returned but only by string. To get the type, I have to do:
diAssemblies[k].GetType(diAssemblies[k].GetName().Name + "." + returnType)
Where returnType is the name of type being returned.
Ideally, I'd like to be able to get the result of the method invocation in to a strongly typed field.
CONTEXT
I'm loading assemblies containing .edmx files from a directory, then invoking methos on those contexts. At run time, the loader won't know what assemblies it's going to be loading. However, the person using the loader will be aware of the assemblies, methods and types.
This is to create a generic wrapper around database calls through entity framework (with stored procedures), that will be reused elsewhere.
If you don't know the Type statically, how could you use a statically typed reference? What you can do is have the returned type implement an interface you do know about statically, then cast to that interface.
So, if MyStrongType implements IMyStrongBehavior, you can cast the return value to IMyStrongBehavior and use that statically. The underlying value is already strongly typed, regardless of whether you cast it.
Alternately, you can store the return value in a dynamic variable (which will allow you to invoke known methods without an actual statically-typed interface.) The disadvantage here is that you don't get any Intellisense and any mistakes you make won't show up until runtime.
No, you can't get the advantages of a concrete type such as compile time checking and intellisense. This is because you are only actually working out what the type is at run time. It is late bound, which means that it's a job for dynamic and the DLR. You can cast it to an object that you know the actual object will inherit from (e.g. object), but you can't cast to the actual type. You might want to look into generics as an alternative if you had for example:
public T GetReturnVal<T>()
{
return (T)context.GetType().InvokeMember(MethodName, BindingFlags.InvokeMethod, null, context, lParams.ToArray());
}
You would at least be returning a concrete type to callers of type T. But this type has to be set at compile time, i.e. known in advance.
I recomend you read An Introduction to C# Generics as it does exactly what, from the context you've added, you need to do.
I am trying to simply load a dll written in C# at run time and create an instance of a class in that dll.
Assembly a = Assembly.LoadFrom(#"C:\Development\DaDll.dll");
Type type = a.GetType("FileReleaseHandler", true);
TestInterface.INeeedHelp handler = Activator.CreateInstance(type) as TestInterface.INeeedHelp;
No errors are thrown, and if I step through the code I can walk though the FileReleaseHandler Class as it executes the constructor but the value of handler is always null.
What am I missing here? or even is there a better way I should be going about this?
Where is TestInterface.INeedHelp defined? One common problem is if you've got the same interface in multiple assemblies. If both the caller and the dynamically loaded assembly reference the same interface in the same assembly, it should be okay.
One subtlety is that if the assembly is in a different directory to the calling assembly, it may end up loading a different copy of the same assembly, which can be very irritating :(
Try setting the result of Activator.CreateInstance to an object directly, and not casting.
It's possible FileReleaseHandler does not implement TestInterface.INeeedHelp, in which case, this will be set to null via the "as TestInterface.INeeedHelp".
Check the assemblies that are loaded into the application domain. Are there two assemblies with the TestInterface.INeedHelp interface in it? My suspicion is that the LoadFrom is binding this created object to a different TestInterface.INeedHelp than the one to which you are trying to cast. Try doing a normal downcast rather than a so-called "safe" cast and see what error you get.
The problem is that the LoadFrom method loads the dll into "LoadFrom" context which is different from the default context. The rules of type resolution for the types in this context differ from the ones you are used to. It is possible that the INeedHelp interface as defined in your main module from the standpoint of the runtime is different from the interface with the same name as coming from the LoadFrom context. This will cause the cast (as TestINterface) return null.
To see if this is the case try to assign the result to an object.
I would do something like :
Assembly a = Assembly.LoadFrom(#"C:\Development\DaDll.dll");
object obj = a.CreateInstance("fullClassName",other params) as IMyType
//(if it implements an interface you referenced)
I have an application that uses plugins that are managed via an interface I then dynamically load the plugin classes and cast them to the interface to work with them.
I have the following line of code, assume that IPlugin is my interface.
IPlugin _plugin = (IPlugin)Activator.CreateInstance(oInfo.Assembly, oInfo.FullyQualifiedName)
This should be pretty simple, create the instance and cast it to the interface. I know that the assembly and fully qualified name values are correct, but I am getting the following exception.
Exception=
System.InvalidCastException: Unable to
cast object of type
‘System.Runtime.Remoting.ObjectHandle’
to type
‘MyNamespace.Components.Integration.IPlugin’.
at
MyNamespace.Components.Integration.PluginProxy..ctor(Int32
instanceId)
Any ideas what could cause this?
The exception indicates that you're getting an ObjectHandle, which suggests that your object is being marshaled and must be unwrapped.
Try the following
ObjectHandle marshaled_plugin = (ObjectHandle)Activator.CreateInstance(oInfo.Assembly, Info.FullyQualifiedName);
IPlugin plugin = (IPlugin)marshaled_plugin.Unwrap();
As you can see in the documentation, this overload returns an ObjectHandle object that wraps the new instance.
The ObjectHandle cannot be casted directly to your interface.
Instead, you need to call the Unwrap method, like this:
IPlugin _plugin = (IPlugin)Activator.CreateInstance(...).Unwrap();