I'm attempting to create an instance of a DirectoryEntry so that I can use this to test some code that will be passed a DirectoryEntry. However, despite a lot of trying I can't find a way to instantiate a DE and initialize it's PropertyCollection.
I have the following code which was taken and modified from another answer on SO that was doing the same process but for the SearchResult object. It seems that the Add method has been completely disabled and I can't find a way to call a constructor on PropertyCollection to pass in some properties.
using System.Collections;
using System.DirectoryServices;
using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;
public static class DirectoryEntryFactory
{
const BindingFlags nonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
const BindingFlags publicInstance = BindingFlags.Public | BindingFlags.Instance;
public static DirectoryEntry Construct<T>(T anonInstance)
{
var e = GetUninitializedObject<DirectoryEntry>();
SetPropertiesField(e);
var dictionary = (IDictionary)e.Properties;
var type = typeof(T);
var propertyInfos = type.GetProperties(publicInstance);
foreach (var propertyInfo in propertyInfos)
{
var value = propertyInfo.GetValue(anonInstance, null);
var valueCollection = GetUninitializedObject<PropertyValueCollection>();
var innerList = GetInnerList(valueCollection);
innerList.Add(value);
var lowerKey = propertyInfo.Name.ToLower(CultureInfo.InvariantCulture);
// These both throw exceptions saying you can't add to a PropertyCollection
//(typeof(PropertyCollection)).InvokeMember("System.Collections.IDictionary.Add", nonPublicInstance | BindingFlags.InvokeMethod, null, dictionary, new object[] { propertyInfo.Name, value });
//dictionary.Add(lowerKey, propertyCollection);
}
return e;
}
private static ArrayList GetInnerList(object propertyCollection)
{
var propertyInfo = typeof(PropertyValueCollection).GetProperty("InnerList", nonPublicInstance);
return (ArrayList)propertyInfo.GetValue(propertyCollection, null);
}
private static void SetPropertiesField(DirectoryEntry e)
{
var propertiesField = typeof(DirectoryEntry).GetField("propertyCollection", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
propertiesField.SetValue(e, GetUninitializedObject<PropertyCollection>());
}
private static T GetUninitializedObject<T>()
{
return (T)FormatterServices.GetUninitializedObject(typeof(T));
}
}
usage is intended to be
DirectoryEntry e = DirectoryEntryFactory.Construct(new { attr1 = "Hello", attr2 = "World"});
I'm hoping I've missed something as I'm pretty new to using reflection in anger.
I'm not familiar with DirectoryEntry itself, but I'm a big fan of the Adapter pattern for testing. It is an annoyance that you would have to do such a thing, but the code itself is trivial and the classes can be placed in a project folder to hide them away from your main project.
For example, I have a FileInfoAdapter and DirectoryInfoAdapter that wrap those classes that touch the filesystem.
FileInfoAdapter:
public class FileInfoAdapter : IFileInfo
{
private readonly FileSystemInfo _fi;
public FileInfoAdapter(string fileName)
: this(new FileInfo(fileName))
{ }
public FileInfoAdapter(FileSystemInfo fi)
{
_fi = fi;
}
public string Name { get { return _fi.Name; } }
public string FullName { get { return _fi.FullName; } }
public bool Exists { get { return _fi.Exists; } }
}
Related
This is a slightly modified version of the question I asked before here.
The actual position is like below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace cns01
{
class Program
{
public class DataFieldInfo2<T>
{
public bool IsSearchValue { get; set; } = false;
public T Value { get; set; }
}
public class SmartRowVertrag
{
public DataFieldInfo2<int> ID { get; set; }
public DataFieldInfo2<string> VSNR { get; set; }
}
static void Main(string[] args)
{
SmartRowVertrag tester = new SmartRowVertrag();
tester.ID = new DataFieldInfo2<int>() { Value = 777, IsSearchValue = false };
tester.VSNR = new DataFieldInfo2<string>() { Value = "234234234", IsSearchValue = true };
var g = RetData3(tester);
}
public static object RetData3(object fsr)
{
object retVal = new object();
var props = fsr.GetType().GetProperties();
foreach (var prop in props)
{
PropertyInfo propInfo = prop.GetType().GetProperty("IsSearchValue"); // <-- here I get null
propInfo = prop.PropertyType.GetProperty("IsSearchValue"); // here I get a propertyInfo, but...
dynamic property = propInfo.GetValue(fsr, null); // ...<-- here fires error
var result = property.IsSearchValue;
if (result == true)
{
// doThis
}
}
return retVal;
}
}
}
I do need to get the boolean value stored in IsSearchValue to to accomplish things.
Thanks beforehand.
I mostly appreciate any helping answer.
fsr is the SmartRowVertrag. You're trying to get the IsSearchValue from that - but it doesn't exist.
Instead, you'll need to call GetValue twice - once on prop, passing in fsr (so which is equivalent to using fsr.ID or dsr.VSNR) and then once on propInfo passing in the result of that first call.
Next, your dynamic use is trying to get IsSearchValue on the result of propInfo.GetValue() - you're trying to evaluate something.IsSearchValue.IsSearchValue, effectively.
Here's corrected code for that part:
public static object RetData3(object fsr)
{
object retVal = new object();
var props = fsr.GetType().GetProperties();
foreach (var prop in props)
{
PropertyInfo propInfo = prop.PropertyType.GetProperty("IsSearchValue");
if (propInfo != null)
{
object fieldInfo = prop.GetValue(fsr);
object isSearchValue = propInfo.GetValue(fieldInfo);
if (isSearchValue.Equals(true))
{
Console.WriteLine($"{prop.Name} has a searchable field");
}
}
}
return retVal;
}
You could avoid using reflection twice though if you had either a non-generic interface that DataFieldInfo2<T> implemented, or a base class. For example:
public interface IDataFieldInfo
{
bool IsSearchValue { get; }
}
public class DataFieldInfo2<T> : IDataFieldInfo
{
...
}
You could then make your reflection code much clearer:
public static object RetData3(object fsr)
{
var fieldProperties = fsr.GetType().GetProperties()
.Where(prop => typeof(IDataFieldInfo).IsAssignableFrom(prop.PropertyType));
foreach (var fieldProperty in fieldProperties)
{
var field = (IDataFieldInfo) fieldProperty.GetValue(fsr);
if (field.IsSearchValue)
{
Console.WriteLine($"{fieldProperty.Name} is a search value field");
}
}
// We don't actually know what you're trying to return
return null;
}
Recently I was writing a method to construct a graph with the dependencies between classes using Reflection and found the following problem. My method analyzes the return type of property, generic arguments of class definition and instance fields of those classes.
For inspection of instance fields of class I use the following method.
public static IEnumerable<FieldInfo> GetFields(Type classType)
{
return classType
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
}
To test it, I write the following class definition:
static void Main(string[] args)
{
foreach (var fieldInfo in GetFields(typeof(A)))
Console.WriteLine(fieldInfo.Name);
Console.ReadKey();
}
class A
{
private ulong? _field1;
public byte PropertyA { get; set; }
public int PropertyB { get; set; }
public bool PropertyC { get; set; }
}
I was in shock for a few seconds, to see the result. It was when I remembered that .NET generates an instance field, Set and Get methods to emulate the properties.
When I inspected with .NET Reflector the library to see the code generated by the compiler, I find the following definition.
class A
{
private ulong? _field1;
[CompilerGenerated]
private Byte <PropertyA>k__BackingField;
[CompilerGenerated]
private Int32 <PropertyB>k__BackingField;
[CompilerGenerated]
private bool <PropertyC>k__BackingField;
}
So I modified the method to exclude the fields with CompilerGenerated attribute and his name match with some property.
public static IEnumerable<FieldInfo> GetFields(Type classType)
{
var regex = new Regex(#"^<(?<PropertyName>\w+)>\w+$");
var fieldInfoes = classType
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var fieldInfo in fieldInfoes)
{
if (fieldInfo.GetCustomAttribute<CompilerGeneratedAttribute>() == null)
yield return fieldInfo;
else
{
var match = regex.Match(fieldInfo.Name);
if (!match.Success)
continue;
var propertyName = match.Groups[#"PropertyName"].Value;
if (classType.GetProperty(propertyName) == null)
yield return fieldInfo;
}
}
}
QUESTIONS
There is some combination of BindingFlags I'm missing for these fields?
There is another way of getting these fields because this code appears to me that is like killing a mosquito with a bazooka?
You can download the complete code here.
You need the fields that are: !field.IsDefined(typeof(CompilerGeneratedAttribute), false)
public static IEnumerable<FieldInfo> GetFields(Type classType)
{
var allFields = classType
.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
var definedFields = from field in allFields
where !field.IsDefined(typeof(CompilerGeneratedAttribute), false)
select field;
return definedFields;
}
I am trying to determine the list of fields involved in the return type (in this case "string MyName" and "string MyAddress" from class Ob along with their respective docstrings).
I got to the stage of obtaining the return type but anything else I try is either giving me blank values or throwing an exception. Any suggestions?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace SampleProf
{
class Program
{
static void Main(string[] args)
{
Sample cl = new Sample();
Type myClType = cl.GetType();
MethodInfo[] methodsInfo = myClType.GetMethods();
List<string> MethodList = new List<string>();
// Iterate through all methods
foreach (MethodInfo methodInfo in methodsInfo)
{
if (methodInfo.IsPublic && methodInfo.Name.Contains("Get") && !methodInfo.Name.Contains("GetType"))
{
if (methodInfo.ReturnType != typeof(void))
{
// Do something here?
}
}
}
Console.Read();
}
}
public class Sample
{
public Ob GetMe()
{
return null;
}
}
public class Ob
{
/// <summary>My name</summary>
string MyName;
/// <summary>My address</summary>
string MyAddress;
}
}
These are properties or fields?
For properties, it's real easy, just similar to how you've already retrieved the methods.
PropertyInfo[] pi = myClType.GetProperties();
For Fields, something like this (using a bitwise OR for the BindingFlags parameter):
myClType.GetFields(BindingFlags.Public | BindingFlags.NonPublic);
I think what you're looking for is methodInfo.ReturnType.GetFields()
Once you have obtained an array of MethodInfo objects you can proceed to iterate over each element in the array, querying the MethodInfo.ReturnType property to determine the type each function returns.
Once you have obtained an instance of Type it is very easy to reflect the fields contained within and print their types and names respectively.
I replaced your somewhat cumbersome condition checking with appropriate BindingFlags when suitable. You no longer need to check if the method is public neither do you need to check if the method is called "GetType".
static void Main(string[] args)
{
Sample sampleInstance = new Sample();
Type sampleType = sampleInstance.GetType();
MethodInfo[] sampleMethods =
sampleType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
foreach (MethodInfo method in sampleMethods)
{
var methodReturnType = method.ReturnType;
if (methodReturnType == typeof(void))
break;
Console.WriteLine(methodReturnType.FullName);
foreach (FieldInfo field in methodReturnType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
{
Console.WriteLine(" {0}: {1}", field.DeclaringType, field.Name);
}
}
Console.Read();
}
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;
}
I want to make a C# Dictionary in which the key is the string name of a static property in a class and the value is the value of the property. Given a static property in the class called MyResources.TOKEN_ONE, how can I get the at the name of the property rather than its value? I only care about the end part of the property name (e.g. "TOKEN_ONE").
I've edited this to mention that I don't want to map all property values in the Dictionary, just a small subset of everything that's in the class. So assume that I want to get the name for a single property. Given MyResources.TOKEN_ONE, I want to get back "MyResources.TOKEN_ONE" or just "TOKEN_ONE".
Here's some sample code that shows what I'm trying to do. I need the property name because I'm trying to generate a javascript variable in which I map the property name to the variable name and the property value to the variable value. For example, I want the C# Dictionary to generate lines like the one below:
var TOKEN_ONE = "One";
using System;
using System.Collections.Generic;
namespace MyConsoleApp
{
class Program
{
static void Main(string[] args)
{
Dictionary<String, String> kvp = new Dictionary<String, String>();
// How can I use the name of static property in a class as the key for the dictionary?
// For example, I'd like to do something like the following where 'PropertyNameFromReflection'
// is a mechanism that would return "MyResources.TOKEN_ONE"
kvp.Add(MyResources.TOKEN_ONE.PropertyNameFromReflection, MyResources.TOKEN_ONE);
kvp.Add(MyResources.TOKEN_TWO.PropertyNameFromReflection, MyResources.TOKEN_TWO);
Console.ReadLine();
}
}
public static class MyResources
{
public static string TOKEN_ONE
{
get { return "One"; }
}
public static string TOKEN_TWO
{
get { return "Two"; }
}
}
}
If all you want is just to be able to refer to a single, specific property in one place in the code without having to refer to it by a literal string, then you can use an expression tree. For example, the following code declares a method that turns such an expression tree into a PropertyInfo object:
public static PropertyInfo GetProperty(Expression<Func<string>> expr)
{
var member = expr.Body as MemberExpression;
if (member == null)
throw new InvalidOperationException("Expression is not a member access expression.");
var property = member.Member as PropertyInfo;
if (property == null)
throw new InvalidOperationException("Member in expression is not a property.");
return property;
}
Now you can do something like this:
public void AddJavaScriptToken(Expression<Func<string>> propertyExpression)
{
var p = GetProperty(propertyExpression);
_javaScriptTokens.Add(p.Name, (string) p.GetValue(null, null));
}
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(() => Tokens.TOKEN_ONE);
AddJavaScriptToken(() => Tokens.TOKEN_TWO);
}
Here is a function that will get you the names of all static properties in a given type.
public static IEnumerable<string> GetStaticPropertyNames(Type t) {
foreach ( var prop in t.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) ) {
yield return prop.Name;
}
}
If you want to build up the map of all property names to their values you can do the following
public static Dictionary<string,object> GetStaticPropertyBag(Type t) {
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
var map = new Dictionary<string,object>();
foreach ( var prop in t.GetProperties(flags) ) {
map[prop.Name] = prop.GetValue(null,null);
}
return map;
}
Now you can call it with the following
var bag = GetStaticPropertyBag(typeof(MyResources));
You can accomplish this with reflection. The easiest way to get the property names is to loop over all of them.
foreach(var propInfo in this.GetType().GetProperties()) {
var name = propInfo.Name;
var value = propInfo.GetValue(this, null);
}
See GetProperties() and GetValue() for more specifics.
Well, I'm reluctantly answering my own question because I don't think it's possible to do this for a single static property. Ultimately, I ended up hard-coding the key in the Dictionary using a cut-and-paste of the property name. Here's what I ended up with:
public void RegisterJavaScriptTokens()
{
AddJavaScriptToken(Token.FOOBAR_TITLE, "FOOBAR_TITLE");
}
And here's the rest of the code:
protected Dictionary<String, String> _javaScriptTokens = new Dictionary<String, String>();
public void AddJavaScriptToken(string tokenValue, string propertyName)
{
_javaScriptTokens.Add(propertyName, tokenValue);
}
protected override void OnPreRender(EventArgs e)
{
if (_javaScriptTokens.Count > 0)
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<String, String> kvp in _javaScriptTokens)
{
sb.AppendLine(String.Format("var TOKEN_{0} = unescape('{1}');", kvp.Key, PUtilities.Escape(kvp.Value)));
}
ClientScript.RegisterStartupScript(this.GetType(), "PAGE_TOKENS", sb.ToString(), true);
}
base.OnPreRender(e);
}
I hate having to use cut-and-paste hard-coding to keep the property name and the key in sync...Oh well...
Other answers have already explained how you can get a list of the static properties via Reflection. You said you don’t want all of them, only a subset of them. It seems, therefore, that you need a way to distinguish the properties you want from the ones you don’t want. One way to do this is using custom attributes.
Declare a custom attribute class:
[AttributeUsage(AttributeTargets.Property)]
public class WantThisAttribute : Attribute { }
Add this custom attribute to the properties you want:
public static class MyResources
{
[WantThis]
public static string TOKEN_ONE { get { return "One"; } }
[WantThis]
public static string TOKEN_TWO { get { return "Two"; } }
public static string DontWantThis { get { return "Nope"; } }
}
Iterate over the properties to find the ones you want:
public static Dictionary<string, object> GetStaticPropertyBag(Type t)
{
var flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
var map = new Dictionary<string, object>();
foreach (var prop in t.GetProperties(flags))
if (prop.IsDefined(typeof(WantThisAttribute), true))
map[prop.Name] = prop.GetValue(null,null);
return map;
}