I am trying to load the old version of farpoint dll in my project by using below code
System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(#"FarPoint.Web.Spread.dll");
System.Type MyDLLFormType = assembly.GetType("FarPoint.Web.Spread.FpSpread");
var c = Activator.CreateInstance(MyDLLFormType);
The problem is after the instance is created, all the available methods of farpoint are not available
[ for example - if i create the object directly the methods like saveExcel or savechanges are available with the instance]
FpSpread fpProxyObject = new FpSpread();
fpProxyObject.SaveExcel();
They are available, just not at compile time. Activator.CreateInstance() returns an object. You could of course cast the object:
var c = Activator.CreateInstance(...)
FpSpread fpProxyObject = (FpSpread)c;
But that would probably beat the whole purpose of using reflection to create the instance.
You can access all members of the result object by using reflection, ie:
MethodInfo saveExcelMethod = c.GetType().GetMethod("SaveExcel");
if (saveExcelMethod == null) throw new ApplicationException("Incorrect version of FarPoint");
saveExcelMethod.Invoke(c);
Intellisense is not working, because, as said #C.Evenhuis, Activator.CreateInstance returns object, so you should cast it to appropriate type.
If type is not known at compile time, but you have access to a code-base, you could try to add interface for it, and implement it by your class. Then cast object to that interface and use it. (I don't know your purpose, but interface could be treated as a contract for all the types, that you will load dynamically).
If type is not known at compile time and you have no access to a code-base, you could use reflection for method invocation or use dynamic instead.
dynamic c = Activator.CreateInstance(MyDLLFormType);
c.SaveExcel(); // this method invocation will be bound in runtime.
By the way be carefull, while using Assembly.LoadFile. You may get more details from this article.
Related
I've got a legacy vb.net dll referenced in my c# project.
calling the various methods no problem, but I need to be able to display a form from the dll, so users can pick the right line from a database response.
Assembly assembly = Assembly.LoadFile("FMSValidation.dll");
produces no error, but
Type type = assembly.GetType (FMSValidation.CreditorDetails );
tells me 'CreditorDetails' is a type, which is not valid in the context.
assembly.GetType does not accept an actual type. It accepts a string:
Type type = assembly.GetType("FMSValidation.CreditorDetails");
It wouldn't make sense for assembly.GetType to be able to take a type, since at that point you already have a type.
Once you have a type, you can create an instance of it with the activator class:
var form = (System.Windows.Forms.Form)Activator.CreateInstance(type);
form.ShowDialog();
If CreditorDetails requires any constructor arguments, use an overload of CreateInstance that accepts the array of arguments.
It seems like the compiler knows FMSValidation.CreditorDetails is a type - so I wonder why you are dynamically loading the assembly and trying to use GetType at all. You should just be able to add a reference to the assembly and use its types like you would any other, like new FMSValidation.CreditorDetails().
FMSValidation.CreditorDetails is a type, but it is not an actual Type object. If you want an actual type object, and you can write the name of the type in your source code (ie. it's not in a string variable or something) then you would use typeof(FMSValidation.CreditorDetails) instead of assembly.GetType.
based on this post: Instantiate a class from its textual name
I am trying to access the method inside of instantiated object but it's still an object. We know that it must be casted before we can access the method. In my case, I can't do the cast because the class is dynamic. Is there any solution?
So far my code not to different from that post above. I just need to call the method after instantiated.
Thanks in advance
You have at least two options for dynamic invocation of methods when the usual type-safe methods aren't applicable:
dynamic o = GetSomeObject();
o.SomeMethod();
or:
object o = GetSomeObject();
MethodInfo mi = o.GetType().GetMethod("SomeMethod");
mi.Invoke(o);
Note that the former is simpler and benefits from some compiler and run-time support (including caching of the dynamic binding) that doesn't occur in the latter example.
have you tried implementing the object as an interface?
or you can also use the 'as' keyword
MyClass test = regularobject as MyClass;
At runtime, I find the type of an object from which I want to create an instance:
string typeName = "myNamespace.type, assembly";
Type theType = Type.GetType(typeName);
// the type features a constructor w/o arguments:
object theInstance = Acivator.CreateInstance(theType);
This works fine and in the debugger I can see all attribute values -- I do assume the debugger uses reflection?
I also have a dynamically deserialized object of type object, for which I know that it in fact of type theType:
// pseudo code on the rhs of the "="
object deserialized = decoder.decode(serializedObject.body);
Is there a way to assign deserializedto theInstance, without looping over the attributes of the type using reflection? Since this will be time critical: assuming the only way to do this is reflection, is there a way to minimize the performance penalty? I do expect many of these objects in short time.
(This is .Net 3.5, so if Type dynamic could solve this it is of no use in this case).
The simplest way would be to write a method that copies the attributes from one object of this type to another:
static void CopyAttributesOnto(theType dest, theType source)
{
dest.a = source.a;
dest.b = source.b;
// ...
}
// Then you can just do this:
CopyAttributesOnto((theType)theInstance, (theType)deserialized);
Another option would be to build a DynamicMethod at runtime and create a delegate from it. You will pay once for the cost of reflection and JIT compilation of the new method, but every invocation of the method will have no more overhead than the use of any other delegate.
Is it possible to determine what type a dynamic member access expects? I've tried
dynamic foo = new MyDynamicObject();
int x = foo.IntValue;
int y = (int)foo.IntValue;
And in the TryGetMember intercept GetMemberBinder.ReturnType is object either way. I also implemented TryConvert wondering if it might get invoked to do the conversion, but it never is hit.
Is there some other override I'm missing that lets me determine what Type the caller wants so that I can do the appropriate conversion?
In C#, when using dynamic, the compiler always sets the binder to return type of object, and then does a second dynamic implicit conversion to the expected return type. So on a DynamicObject when called from c#, GetMemberBinder.ReturnType will always be object, but that said if you return another sort of springboard dynamic object with TryConvert implemented you could get that type, except if the user does var or dynamic as the variable, then they have a proxy that won't do anything until it becomes statically typed.
ImpromptuInterface does something different but along these lines, because it also has the desire to have a dynamic implementation that changes based on return types -- just you would have to describe the dynamic object via an interface.
In VB (ASP.NET)
Application("myapp")= Server.CreateObject("APP.Engine")
aa = Application("myapp").myMethod(2)
works.
In C# I tried
Application["myapp"]= Server.CreateObject("APP.Engine")
but
Application["myapp"].myMethod(2)
fails with
'object' does not contain a definition for 'myMethod'
How can I expose the public interface in C#?
If you have access to the defining type (i.e. not a raw COM object), you can simply cast:
((APP.Engine)Application["myapp"]).myMethod(2);
If you are using c# 4.0, you can do:
dymamic myApp = Application["myapp"];
myApp.myMethod(2);
Otherwise you will have to use dynamic method invocation using reflection and Type.InvokeMember(...)
You need to cast to the correct class first, like:
((APP.Engine)Application["myapp"]).myMethod(2)
Cast the result of Application["myapp"] to the correct type, like so:
((APP.Engine)Application["myapp"]).myMethod(2);
Other options include creating a local reference and using that instead.
This basically happens as C# is strongly typed language. When you call Application you are actually calling a collection of type Object. The collection is actually an array of Object. We take it as object because it will enable you to store almost anything to the collection.
Now Application["myapp"] will eventually return an object of System.Object type.
So you need to typecast the object to your type.
App.Engine obj = Application["myapp"] as App.Engine;
if(obj != null)
obj.myMethod(2);
The object obj is a reference to the actual type and the compiler will not throw any exception if you call myMethod(2).
Just remember one thing while converting code from VB to C# is, C# is the strongly typed language and before you access any type, you will need to convert it. However same wasn't required in VB.
So for this example you would need to use App.Engine for type conversion.
((APP.Engine)Application["myapp"]).myMethod(2)