Pass MakeGenericMethod a Dynamic Type - reflection

I'm trying to call a generic method and need to pass it a Type dynamically. But get a compile error, 'CS0246: The type or namespace name `t' could not be found. Are you missing a using directive or an assembly reference'. Please tell me what I'm overlooking, thank you.
...in the main...
Type t = DiscoverType(field); // returns Type given FieldInfo via Type.GetType(string)
MethodInfo method = typeof(testClass).GetMethod("MyGenericMethod", BindingFlags.NonPublic | BindingFlags.Instance);
MethodInfo generic = method.MakeGenericMethod(typeof(t));
object[] args = {field};
generic.Invoke(this, args);
the generic method...
private void MyGenericMethod<T>(FieldInfo field)
{
field.SetValue(obj, new List<T>(objList));
}

Hard to know what exactly you are trying to do, but you can fix your compiler error like this:
MethodInfo generic = method.MakeGenericMethod(t);
You use the typeof operator to go from a type-name to a System.Type instance. In your case, you already have the System.Type instance you need so typeof isn't useful here.

Related

Ienumerable of T, T is only available at runtime

I have a method with this signature
public IEnumerable<T> GetAll<T>() where T : new()
{
// Orm Lite Version
return Connection.LoadSelect<T>();
}
At compile time I don't know the Type T. I only know the class name at runtime is it possible to call this method using reflection with something like this?
string TargetTBLName = ...;//TargetTBLName get's it's value at runtime
Type ParentTableClass = Type.GetType(TargetTBLName);
IEnumerable<Type.GetType(TargetTBLName)> test = Repository.GetAll<Type.GetType(TargetTBLName)>();
Any Ideas?
I'd give a Dynamitey library a go. You can do that in many different ways, but I prefer this one because of its simplicity. You can find it here.
var name = InvokeMemberName.Create;
var test = Dynamic.InvokeMember(Repository, name("GetAll", new[]{ParentTableClass }));
foreach(var obj in test)
{
obj.SomeMethodFromMyType();
}
Keep in mind, that if Repository is static, than you have to tweak it a bit to use static invocation context (look up the link).
Now you have a test object, which is a dynamic - you can use it with duck typing (which has some implications on speed, for example), but in general you can do whatever you want to do with a normal IEnumerable<YourType>.
If you want to use reflection:
MethodInfo getAll= typeof(Repository).GetMethod("GetAll");
MethodInfo getAllGeneric= getAll.MakeGenericMethod(ParentTableClass);
object result = getAllGeneric.Invoke(this, null);
//or null, null is Repository is static
var finalObject = result as IEnumerable;
Mind that since this ParentTableClass is an unknown during compilation, you won't have access to anything that the actual type provides - unless you use dynamic approach.

adding a new constructor to "existing" type with mono.cecil

I am trying to add new overloaded constructor to an existing type.
I tried to do it with emit namespace, however created type doesnt inherit the base class and all other methods.
And after reading some articles, i decided its not possible with .net framework built-in classes.
So I got Mono.Cecil, but couldnt find any decent example how to achieve this.
I have encountered a sample which copies methods, but not props, fields etc.
This adds an empty constructor
void AddEmptyConstructor(TypeDefinition type, MethodReference baseEmptyConstructor)
{
var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
var method = new MethodDefinition(".ctor", methodAttributes, ModuleDefinition.TypeSystem.Void);
method.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
method.Body.Instructions.Add(Instruction.Create(OpCodes.Call, baseEmptyConstructor));
method.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
type.Methods.Add(method);
}
You will need to extend it to pass through the extra parameters.
From here

Retrieve private methods of a class using reflection

I want to retrieve the private (implementation and other) methods of a class which implements an interface and also is derived from (inherits) a base class.
How can I achieve this using reflection?
Is there another way to achieve this?
This is what I'm trying to do. I need to view these private methods and their contents. I don't want to invoke them.
Dim assembly As System.Reflection.Assembly
Dim assemblyName As String assemblyName = System.IO.Path.GetFullPath("xyz.dll")
assembly = System.Reflection.Assembly.LoadFile(assemblyName)
assembly.GetType("myClass").Getmethods(Bindings.NonPublic)
assembly.GetType("myClass").GetMethods(BindingFlags.NonPublic) isn't working.
Making the assumption that you're trying to use the private methods of a 3rd party assembly:
I'd urge caution in using private methods, they have been made private for a reason and
might rely on some state that you won't be able to anticipate; Also, if the assembly gets updated in the future, the private behavior may be changed or removed causing you to have to re-write your code to compensate.
However, there are two methods at your disposal, if you want to continue.
One way us using the new Dynamic keyword in .net 4:
http://igoro.com/archive/use-c-dynamic-typing-to-conveniently-access-internals-of-an-object/
To use reflection, this question may help you:
How do I use reflection to invoke a private method?
Hope this helps.
BindingFlags
You must specify Instance or Static along with Public or NonPublic or no members will be returned.
Assembly myAssembly;
myAssembly = Assembly.LoadFrom(#"c:\xyz.dll");
Type myType = myAssembly.GetTypes()[0]; //change 0 according to your class type.
BindingFlags eFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
MethodInfo myMethod = myType.GetMethod("Methodname", eFlags);
object obj1 = myAssembly.CreateInstance(myType.FullName);
object obj2 = myMethod.Invoke(obj1, new object[2] { parameters1, parameters1 });

How do I create a shallow copy of an object so that it may be serialize and sent via a web method call?

I would like to serialize the properties of the HttpBrowserCapibilities object so that it may be returned via a web method call. Currently the object cannot be serialized:
Cannot serialize member System.Web.Configuration.HttpCapabilitiesBase.Capabilities of type System.Collections.IDictionary, because it implements IDictionary.
...which is understandable. However, I would like to simply copy out the properties and their values to a hierarchy, i.e.
<HttpBrowserCapabilities>
<IsMobile>true</IsMobile>
</HttpBrowserCapabilities>
I'm starting to think I would need to use reflection to copy this object, but I haven't reached a conclusion. Does anyone have any suggestions to keep this simple?
Thanks,
George
Originally I posted an answer using XmlDocument, but I glossed over some of the web method stuff and didn't realize you were really trying to map a DTO.
Reflection sounds complicated but it really isn't. The following snippet will do what you want:
public static void Populate(object dest, IDictionary dictionary)
{
Type t = dest.GetType();
foreach (object key in dictionary)
{
PropertyInfo prop = t.GetProperty(key.ToString(),
BindingFlags.Instance | BindingFlags.Public);
if ((prop != null) && prop.CanWrite)
{
object value = dictionary[key];
prop.SetValue(dest, value, null);
}
}
}
Then invoke this as:
BrowserCapsDto dto = new BrowserCapsDto();
Populate(dto, Capabilities); // Capabilities is the real BrowserCaps
It's pretty easy because you already have an IDictionary and thus you already know all of the possible names you can map; you don't actually need to use any reflection on the source, just the destination.

How do I create an instance of a class in an ASP.NET application

How do you go about creating an instance of an object when given the class name as a string in an ASP.NET v2 application? For example, I've got a class called SystemLog defined in the app_code section of the application. The class is defined within the Reports namespace. To create an instance of the object, I do something like this:
Dim MyObject As New Global.Reports.SystemLog
However, I want to create this object using a string to define the type. The type name is stored in a SQL database as a string. I thinks it's probably something to do with Activator.CreateInstance(AssemblyName, TypeName) but what I don't know is what to pass in those strings. What is the assembly name of an ASP.NET web app?
Help!
Thanks, Rob.
PS. I don't want a hard coded Select statement :-)
string typeName = "Your Type Name Here";
Type t = Type.GetType(typeName);
object o = Activator.CreateInstance(t);
This will give you an instanciated type. If will be up to you to cast it to the correct type and call your appropriate methods.
If you need to create a type that doesn't have a parameterless constructor there is an overload on CreateInstance that takes a params of objects to pass to a constructor. More info at this MSDN article.
The following is able to create type, even if it's from another assembly:
public object CreateInstance(string typeName) {
var type = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(a => a.GetTypes())
.FirstOrDefault(t => t.FullName == typeName);
return type.CreateInstance();
}
You can use this to get it from a particular assembly:
Assembly assembly = Assembly.Load("myAssembly");
Type ObjectType = assembly.GetType("Type name here");
then.....object o = Activator.CreateInstance(ObjectType);

Resources