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;
Related
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.
I have some method with the following definition;
public void SomeMethod<T>() where T : BaseClass, new()
{
InheritedClass instance = (InheritedClass)instanceOfT; //won't compile
}
Why is that cast not allowed? How can you get around this? I have about 200 lines of code which is all suited for generics except I need a one LINQ query for each of the inheriting classes (there are 3). I was trying to do a typeof check, then follow that with a cast, then execute the appropriate query but the compiler won't let me do the cast... Given I just checked to ensure that T is in fact an instance of type InheritedClass there is no way it would fail, why won't the compiler let me do it?
You need to cast the variable to object and then back down to do this. As it is the compiler believes that there is no possible way that the cast could succeed, but it doesn't ever apply that check to variables of type object.
InheritedClass instance = (InheritedClass)(object)instanceOfT;
Because the actual instanceOfT's type (let's call it InheritedClassB) may not be related to InheritedClass.
Given I just checked to ensure that T is in fact an instance of type InheritedClass
Actually, you're only checking that T extends BaseClass.
Edit: This looks like a code smell.. Can't you let the concrete class handle this method? So each concrete class would have its own implementation, and know how to perform SomeMethod.
I've combed through existing questions/answers on this matter, but none of them spelled out exactly what I was looking for in a way I understood. Here is my snippet:
Type t = **?**
_SecondRole.ProvisionRelationship<t>(_FirstRole);
I believe I'm suppose to use reflection here, though I don't fully understand how. How do I define "t" so this works?
Thank you for any assistance.
If the _FirstRole is an instance of the unknown t, for example from:
object _FirstRole = Activator.CreateInstance(t);
then you can exploit dynamic here:
dynamic _FirstRole = Activator.CreateInstance(t); // or whatever
_SecondRole.ProvisionRelationship(_FirstRole);
The second line is now a dynamic statement, evaluated in part at runtime (but with some clever cache usage) - which means it can perform generic type inference from the actual type of the object dereferenced from _FirstRole.
If that is not the case, then the only way to invoke that is via GetMethod and MakeGenericMethod - which is ungainly and not hugely efficient. In that scenario I would strongly suggest refactoring _SecondRole.ProvisionRelationship to accept a Type parameter rather than just being generic; you can of course still provide a generic version to avoid impacting existing code:
void ProvisionRelationship(Type type, SomeType role) {...}
void ProvisionRelationship<T>(SomeType role) {
ProvisionRelationship(typeof(T), role);
}
and invoke as:
_SecondRole.ProvisionRelationship(t, _FirstRole);
If i have a type and an object eg.:
- Type someType (coming from somewhere, could be any class eg. MyClass.GetType())
- Object someObject (eg. List<MyClass>())
and want to cast the object back to List<MyClass>. How should i do this?
You can't do this. Generics ensure compile-time safety. You cannot have compile time safety because you know the actual type only at runtime.
You have a runtime type and you want to perform a compile time cast. This is not possible. It is also not clear why you would want to do this in the first place. If you are interested in cases that require reflection, perhaps you should investigate that topic further.
There is no way to have compile-time typing a variable when you only receive the Type information at runtime.
This is different from generics since in generics you get the type information at compile time:
void MyFunc<T>(T thing)
{
// T is passed in at compile time
}
In your case you are getting the type at runtime. So while you can't cast the member to the type the way you normally would you can reflect on the instance and call its members:
void MyFunc(object thing, Type type)
{
var res = t.GetMethod("Add").Invoke(a, new []{"someArg"});
}
Casting means explicitly specifying the type you want to convert to. Since you don't know what your type is, you can't cast to it.
That doesn't mean you can't access the list. If you know the object you have is a list of something, you can cast it to the non-generic IList interface, which provides most of the methods and properties you need:
object obj = GetMyList();
IList list = (IList)obj;
object fifthItem = list[4];
list.RemoveAt(list.Count - 1);
If you describe the problem you're trying to solve rather than the solution you are trying to achieve, then more fitting solutions might be posted.
If you are trying to cast a runtime type at compile time, it is impossible as may said before me.
However, you could cheat a little (but don't use this technique excessively, it leads down a dark road...)
public void DoSomething<T>(List<T> object) where T : ....
{
//do what you want here
}
public void CallIt(Type t, object o) //o is List<Foo>
{
this.GetType().GetMethod("DoSomething").MakeGenericMethod(t).Invoke(o);
}
However I don't see any real benefit to this, as if you don't write any type constraint you gain nothing with using generics instead of objects and IList interface, and if you write any baseclass or interface there, you could just cast your object to that. (For example if you know that T implements IFoo, you could cast o to IList<IFoo> and have every benefit of List<Foo>...
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)