How can i get the Key for a specific MyData.Name value?
I dont need to modify the Dictionary
This is the given situation and i need to match "Server" to 1L
public class MyBase
{
protected struct MyData
{
public string Name;
}
}
public class MyClass : MyBase
{
private readonly Dictionary<ulong, MyBase.MyData> m_Data = new Dictionary<ulong, MyBase.MyData>();
public MyClass()
{
m_Data.Add(1L, new MyData { Name = "Server" });
}
}
public class MyMulti
{
public static MyClass myClass = new MyClass();
}
public class Test
{
Type MyDataType = typeof(MyBase).GetNestedType("MyData", BindingFlags.Instance | BindingFlags.NonPublic);
object m_Data = typeof(MyClass).GetField("m_Data", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(MyMulti.myClass);
// How can i get the Key for a specific MyData.Name value?
}
I actualy just found an easy way to do so:
var m_Data = typeof(MyClass).GetField("m_Data", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(MyMulti.myClass) as IDictionary;
foreach (var pair in m_Data.Keys)
{
Console.WriteLine(pair + " = " + m_Data[pair].GetType().GetField("Name").GetValue(m_Data[pair]));
}
Related
I Work on c#/Code first
I've a Parent Class
abstract public class form_base {}
and severals differents childs class.
Here one of them
public class form_Frais : form_base {
}
I've a view with all form_base, but when i click on one, I open a common template.
I just need change the mapping according to child type in changing the controler/Function by an URL
Then In my form_base
I had this :
public T Cast<T>(object o)
{
return (T)o;
}
public dynamic converttt(Type LeTyp)
{
MethodInfo castMethod = GetType().GetMethod("Cast").MakeGenericMethod(new[] { LeTyp });
dynamic castedObject = castMethod.Invoke(Activator.CreateInstance(LeTyp), new object[] { this });
return castedObject;
}
I've split my project in 2 part (engine/Web) My classes are define in engine
My problem is to fill my list of all form_base in web part.
I use this function in controler part
public ActionResult demandeur()
{
object model;
model = new { formsList = (from f in CurrentDBContext.forms_base select f).ToList().getCardModel(false) };
}
return View("demandeur", model);
}
And In web I create extension methods (I won't see in engine part)
public static partial class extensions
{
public static List<formListItem> getCardModel(this List<form_base> items, bool envalidation)
{
List<formListItem> model = new List<formListItem>();
if (items != null && items.Count > 0)
{
foreach (var item in items)
{
Type LeTyp = item.GetType().BaseType;
dynamic castedObject = item.converttt(LeTyp);//Pb here not good type : System.Data.Entity.DynamicProxies.form_Frais_353DEAA5...' ne contient pas de définition pour 'getCardModel''
model.Add(castedObject.getCardModel(envalidation));
}
}
return model;
}
public static formListItem getCardModelBase(this form_base f)
{
formListItem model = new formListItem();
model.id = f.id;
model.libelle = f.title;
model.libelleType = f.formType.title;
model.libelleStatut = f.StatutInterneLibelle;
model.demandeur = f.demandeur.fullName;
model.idtype = f.formType.id;
return model;
}
public static formListItem getCardModel(this form_Frais form, bool envalidation)
{
formListItem model = ((form_base)form).getCardModelBase();
model.URL = "/forms/NoteFrais/InitForm"; //The good URL
model.envalidation = envalidation;
return model;
}
}
I try to put all in extension part like that:
public static T Cast<T>(object o)
{
return (T)o;
}
public static List<formListItem> getCardModel(this List<form_base> items, bool envalidation)
{
List<formListItem> model = new List<formListItem>();
if (items != null && items.Count > 0)
{
foreach (var item in items)
{
Type LeTyp = item.GetType().BaseType;
MethodInfo castMethod = item.GetType().BaseType.GetMethod("Cast").MakeGenericMethod(new[] { LeTyp });
dynamic castedObject = castMethod.Invoke(null, new object[] { item });
model.Add(castedObject.getCardModel(envalidation));
}
}
return model;
}
public static formListItem getCardModelBase(this form_base f)
{
formListItem model = new formListItem();
model.id = f.id;
model.libelle = f.title;
model.libelleType = f.formType.title;
model.libelleStatut = f.StatutInterneLibelle;
model.demandeur = f.demandeur.fullName;
model.idtype = f.formType.id;
return model;
}
But I've error in item.GetType().BaseType.GetMethod("Cast").MakeGenericMethod(new[] { LeTyp }); cause GetMethod("Cast") return null
All my research come from here
UPDATE
In resume, In first try, I've problem of type class return dynamicproxy...
And in static version, I can't find method Cast..
I try
MethodInfo[] methodInfos = LeTyp.GetMethods(BindingFlags.Public | BindingFlags.Static);
But My array is empty... then my problem in static version will be hwo save correctly my Case function??? and use it in extension method
UPDATE 3
I find the problem in static mode
I need tu put Cast function in note_frais class
and use it
Type LeTyp = item.GetType().BaseType;
//MethodInfo[] methodInfos = LeTyp.GetMethods(BindingFlags.Public | BindingFlags.Static);
MethodInfo MI = LeTyp.GetMethod("Cast");//<T>.getMethod(cast)
MI = MI.MakeGenericMethod(typeof(form_base));
dynamic t = MI.Invoke(null, new object[] { item });
model.Add(t.getCardModel(envalidation));
But now I've same pb in 2 parts :
//Pb here not good type : System.Data.Entity.DynamicProxies.form_Frais_353DEAA5...' ne contient pas de définition pour 'getCardModel''
Thanks for your help? I read lot of things but now I'm completly lost.
Instead of:
GetMethod("Cast")
...try this overload:
GetMethod("Cast", new Type[] { typeof(Object) })
More observations...
The Cast<T> method of class form_base is not static. (See above to get this one.)
The class form_base doesn't define any public static methods.
(Side note, I'm not sure why the class extensions is defined as partial.)
The Cast<T> method in class extensions is static, but is not an extension method.
To get this one, you can use this overload, on type extensions:
typeof(extensions).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(Object) }, null)
If you did define the Cast<T> extension method in class extensions:
public static partial class extensions {
public static T Cast<T>(this form_base b, object o) {/*…*/}
}
...then you could get it with the same overload on type extensions, by modifying the types argument:
typeof(extensions).GetMethod("Cast", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(form_base), typeof(Object) }, null)
Finally... With a simple sample it's good
using System;
using System.Collections.Generic;
using System.Reflection;
namespace ConsoleApp1
{
abstract public class form_base
{
public Guid Guid { get; set; }
}
public class form_Frais : form_base
{
public int MonInt { get; set; }
public static T Cast<T>(object o)
{
return (T)o;
}
}
public class form_Avoir : form_base
{
public int MonInt { get; set; }
public static T Cast<T>(object o)
{
return (T)o;
}
}
public static class extensions
{
public static int GetCardModel(this form_Avoir form)
{
return form.MonInt * 100;
}
public static int GetCardModel(this form_Frais form)
{
return form.MonInt * form.MonInt;
}
}
public class TOTO
{
public static int GetCardModel(form_Avoir form)
{
return form.MonInt * 100;
}
public static int GetCardModel(form_Frais form)
{
return form.MonInt * form.MonInt;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
form_Frais nf = new form_Frais();
nf.Guid = Guid.NewGuid();
nf.MonInt = 2;
List<form_base> lst = new List<form_base>();
//MethodInfo[] methodInfos = typeof(form_base).GetMethods(BindingFlags.Public | BindingFlags.Static);
lst.Add(nf);
form_Avoir av = new form_Avoir();
av.Guid = Guid.NewGuid();
av.MonInt = 5;
lst.Add(av);
foreach (dynamic f in lst)
{
Console.WriteLine(TOTO.GetCardModel(f)); // OK
//Type LeTyp = f.GetType();
//MethodInfo MI = LeTyp.GetMethod("Cast");//<T>.getMethod(cast)
//MI = MI.MakeGenericMethod(typeof(form_base));
//dynamic t = MI.Invoke(null, new object[] { f });
//Console.WriteLine(t.GetCardModel());// Error
}
}
}
}
My error was to thought that extension methods was include in object. In fact not. It seems but not really. I just change with a method with parameter instead of extension
I have some not useful object with, let's say, 30 properties. Half of them are useful for me, so I want to create new useful object with only properties I need so the rest doesn't take space in object visualizers. I don't want to define new class and type them down. I want something like
var list = new List<SomeType> { usefulProp1, usefulProp2, ... };
var usefulObject = new NewItem(notUsefulObject, list);
where SomeType is not string (list doesn't contain property names).
if its something permanent then doing it properly would be to create a class that inherits from your base class and populate only the properties that you need.
public UsefulObject : NotUsefulObject
{
public int MyProperty
{
get
{
return base.MyProperty; // this is arbitrary you can do it however you want.
}
set
{
MyProperty = value;
}
}
}
Then you can use your reuse your useful object however you want.
var list = new List<UsefulObject>();
var list = new List<Expression<Func<object>>> { () => notUsefulObject.usefulProp1, () => notUsefulObject.usefulProp2... };
var nm = new AssemblyName("MyDynamicAssembly");
TypeBuilder tb = Thread.GetDomain().DefineDynamicAssembly(nm, AssemblyBuilderAccess.RunAndSave).DefineDynamicModule(nm.Name, nm.Name + ".dll").DefineType("NewItem", TypeAttributes.Public);
const MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
foreach (Expression b in list.Select(x => x.Body))
{
MemberInfo mi = ((MemberExpression)b).Member;
Type t = b.Type;
FieldBuilder fb = tb.DefineField(mi.Name.ToLower(), t, FieldAttributes.Private);
PropertyBuilder pb = tb.DefineProperty(mi.Name, PropertyAttributes.HasDefault, t, null);
MethodBuilder getBld = tb.DefineMethod("get_" + mi.Name, GetSetAttr, t, Type.EmptyTypes);
ILGenerator getGen = getBld.GetILGenerator();
getGen.Emit(OpCodes.Ldarg_0);
getGen.Emit(OpCodes.Ldfld, fb);
getGen.Emit(OpCodes.Ret);
MethodBuilder setBld = tb.DefineMethod("set_" + mi.Name, GetSetAttr, null, new[] { t });
ILGenerator setGen = setBld.GetILGenerator();
setGen.Emit(OpCodes.Ldarg_0);
setGen.Emit(OpCodes.Ldarg_1);
setGen.Emit(OpCodes.Stfld, fb);
setGen.Emit(OpCodes.Ret);
pb.SetGetMethod(getBld);
pb.SetSetMethod(setBld);
}
object usefulObject = Activator.CreateInstance(tb.CreateType());
Because you said this problem was specific to object visualizers, the best solution is to make a Debugger Type Proxy for the class which can be used as a proxy.
[DebuggerTypeProxy(typeof(SomeTypeDebugView))]
public class SomeType
{
public string Foo { get; set; }
public string Bar { get; set; }
internal class SomeTypeDebugView
{
private SomeType _someType;
public SomeTypeDebugView(SomeType someType)
{
_someType = someType;
}
public string Foo { get { return _someType.Foo; } }
}
}
class Program
{
static void Main()
{
var someType = new SomeType();
someType.Foo = "foo";
someType.Bar = "bar";
Debugger.Break();
}
}
This will cause Bar to be hidden in the debug visualizer by default unless you choose to view the "Raw Type"
If you are looking for a more one time debugging type you can use annonamous types to create the new type you need in the watch window, for example his is new {Foo = someType.Foo, Bar = someType.Bar }
This also could be used with LINQ to perform the select over a IEnumerable, here for example is someTypeList.Select(x=> new {Foo = x.Foo, Bar = x.Bar})
Situation:
Currently I am reading all available functions and methods from specific class with reflection. All the functions in the class does have an attribute section like this
[ImportFunctionAttribute("myFunction1", 1, ImportAttribute.SourceType.Type1)]
public ImportStatusDetails myFunction1()
{
}
[ImportFunctionAttribute("myFunction2", 2, ImportAttribute.SourceType.Type2)]
public ImportStatusDetails myFunction2()
{
}
To get all the methods in the given class I use this code
// get the public methods out of import class order by class name
var importMethods = (typeof (Import)).GetMethods(
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
Problem:
Using the GetMethods-Method will give me both functions - but I only want to get the method of type ImportAttribute.SourceType.Type2.
Question:
Is it possible to limit the results of the GetMethods-Method for given CustomAttributes like for example with GetMethods(...).Where() ?? What should I do to resolve this problem?
Addition1
public class ImportFunctionAttribute : Attribute
{
public enum SourceType
{
Unknown = 0,
Type1 = 1,
Type2 = 2
}
public ImportFunctionAttribute(string psTabName, int pnTabId, SourceType pSourceType)
{
tabName = psTabName;
tabId = pnTabId;
source = pSourceType;
}
protected string tabName;
protected int tabId;
protected SourceType source;
public string TabName { get { return tabName; } }
public int TabId { get { return tabId; } }
public SourceType Source { get { return source; } }
}
Thanks in advance.
I believe you're looking for GetCustomAttributes(...).
var methods = new List<MethodInfo>();
var importMethods = (typeof (Import)).GetMethods(
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly));
for (var i = 0; i < importMethods.Length; i++)
{
var attr = importMethods[i].GetCustomAttributes(typeof(ImportFunctionAttribute), false).Cast<ImportFunctionAttribute>();
if (attr.Source == SourceType.Type2)
{
methods.Add(importMethods[i]);
}
}
I'm trying to clone instances of a derived class, but somehow it doesn't work well. The cloning method is:
public static T CloneFieldsAndProperties<T>(T input)
{
T result = (T)Activator.CreateInstance(typeof(T));
PropertyInfo[] listOfProps = typeof(T).GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.CreateInstance);
FieldInfo[] listOfFields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.CreateInstance);
foreach (PropertyInfo prop in listOfProps) prop.SetValue(result, prop.GetValue(input, null), null);
foreach (FieldInfo field in listOfFields) field.SetValue(result, field.GetValue(input));
return result;
}
As you can see, I added many BindingFlags because it wasn't working. But to no avail.
It does work in a simple case:
MyclassA1 a1 = new MyclassA1();
MyclassA a = CloneFieldsAndProperties(a1);
if (a is MyclassA1) Text = "Works";
Where:
class MyclassA
{
public int i;
}
class MyclassA1 : MyclassA
{
public int i1;
}
But in my real program it doesn't. The real program's classes' declarations are long so I'm not posting them here. What might be the problem?
I had the same issue a long time ago. The only real solution for me, after lots of googling, was to serialize and deserialize it. It's not a bad solution and you lose only a little bit of performance, just do it like this:
Add this tag to your class:
[Serializable()]
public class a
{
}
And then you can create a function like this:
public object Clone()
{
IO.MemoryStream mem = new IO.MemoryStream();
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter form = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
form.Serialize(mem, this);
mem.Position = 0;
return form.Deserialize(mem);
}
If you need a shallow clone, simply use Object.MemberwiseClone. If you need a deep clone, serialize and then deserialize your object (e.g. using BinaryFormatter or DataContractSerializer). This would take care of issues such as cycles and cross references.
This will work and may be faster than the serialization method:
Code:
using System;
namespace Cloning
{
class Program
{
static void Main(string[] args)
{
Derived d = new Derived() { property = 1, field = 2, derivedProperty = 3, derivedField = 4 };
Base b = new Derived(d);
// Change things in the derived class.
d.property = 5;
d.field = 6;
d.derivedProperty = 7;
d.derivedField = 8;
// Output the copy so you know it's not shallow.
Console.WriteLine((b as Derived).property);
Console.WriteLine((b as Derived).field);
Console.WriteLine((b as Derived).derivedProperty);
Console.WriteLine((b as Derived).derivedField);
Console.ReadLine();
}
class Base
{
public int property { get; set; }
public int field;
}
class Derived : Base
{
public Derived() { }
public Derived(Derived d)
{
// Perform the deep copy here.
// Using reflection should work, but explicitly stating them definitely
// will, and it's not like it's not all known until runtime.
this.property = d.property;
this.field = d.field;
this.derivedProperty = d.derivedProperty;
this.derivedField = d.derivedField;
}
public int derivedProperty { get; set; }
public int derivedField;
}
}
}
Test:
http://goo.gl/pQnAL
Output:
1
2
3
4
Comments:
I would really imagine that this would work in more than just a trivial case but perhaps not:
public static T CloneFieldsAndProperties<T>(T input)
{
T result = (T)Activator.CreateInstance(input.GetType());
PropertyInfo[] properties = input.GetType().GetProperties();
FieldInfo[] fields = input.GetType().GetFields();
foreach (PropertyInfo property in properties)
property.SetValue(result, property.GetValue(input, null), null);
foreach (FieldInfo field in fields)
field.SetValue(result, field.GetValue(input));
return result;
}
Sorry if the tile is misleading. What i would like to do is to use a string to get the values from a class. What i have:
class foo
{
public string field1 {get;set;}
public string field2 {get;set;}
}
public void run()
{
//Get all fields in class
List<string> AllRecordFields = new List<string>();
Type t = typeof(foo);
foreach (MemberInfo m in t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
AllRecordFields.Add(m.Name);
}
foo f = new foo();
foreach(var field in AllRecordFields)
{
//field is a string with the name of the real field in class
f.field = "foobar";
}
}
This a really simple example, so the problem is on the line f.field = "foobar";
The field is a string with a name of the real class field what i want to assignt the value to.
Use PropertyInfo instead of MemberInfo and then SetValue.
public void run()
{
foo f = new foo();
Type t = typeof(foo);
foreach (PropertyInfo info in t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
{
info.SetValue(f, "foobar", new object[0]);
}
}
First of all, it is better to use Properties instead of fields.
Second your fields are private, can't be accessed from outside foo. You need to declare them as public.
For your example you have to use reflection to access those files. But that is slow and it is not very good style. You better use the class directly (with property setter) or us an interface.
Add method into foo class to change all properties
class foo
{
public string field1 {get;set;}
public string field2 { get; set; }
public void SetValueForAllString( string value)
{
var vProperties = this.GetType().GetProperties();
foreach (var vPropertie in vProperties)
{
if (vPropertie.CanWrite
&& vPropertie.PropertyType.IsPublic
&& vPropertie.PropertyType == typeof(String))
{
vPropertie.SetValue(this, value, null);
}
}
}
}
foo f = new foo() { field1 = "field1", field2 = "field2" };
f.SetValueForAllString("foobar");
var field1Value = f.field1; //"foobar"
var field2Value = f.field2; //"foobar"