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 });
Related
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.
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
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.
I've got a data provider that contains a collection of entities. I only want to be able to create a new entity through the data provider.
I.e, to create a new record I need to use:
Entity entity = Provider.AddNew();
enity.set_Properties... etc
My issue is that if I set my entities to Internal, System.Activator cannot create an Instance of them. Each of my Data Providers uses a Base class with the generic type of the entity passed through.
So at the moment my AddNew() method contains the following:
public T AddNew()
{
T added = Activator.CreateInstance<T>();
this.Collection.Add(added);
return added;
}
It's obviously not the end of the world if I can instantiate a new entity manually outside of the Data Provider namespaces, but it seems pointless considering there's no way to ever save them, so why give the option to do so?
EDIT: Forgot to mention that all my providers, entities, etc are in the same namespace.
Don't use the Activator, which relies on a public constructor. Instead use reflection to find the parameterless constructor and then call it. Something along these lines:
Type t = typeof(MyType);
var parameterlessCtor = (from c in t.GetConstructors(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
where c.GetParameters().Length == 0
select c).FirstOrDefault;
if(parameterlessCtor != null) instance = parameterlessCtor.Invoke(null);
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);