List all SystemColors - c#

In Windows.Forms, I need to create a program which accepts any color and tries to find the corresponding system colors to it.
I was not able to figure out how to loop through all Colors of the System.Drawing.SystemColors class - it's a class, not an enum or a List.
How can I do this (some kind of reflection?)?

How about
public static Dictionary<string,object> GetStaticPropertyBag(Type t)
{
const BindingFlags 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;
}
or
foreach (System.Reflection.PropertyInfo prop in typeof(SystemColors).GetProperties())
{
if (prop.PropertyType.FullName == "System.Drawing.Color")
ColorComboBox.Items.Add(prop.Name);
}

And I cooked something up.
var typeToCheckTo = typeof(System.Drawing.Color);
var type = typeof(System.Drawing.SystemColors);
var fields = type.GetProperties(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public).Where(p => p.PropertyType.Equals(typeToCheckTo));
foreach (var field in fields)
{
Console.WriteLine(field.Name + field.GetValue(null, null));
}

Related

How to set class fields using keys?

I wrote a generic method which should let us send type, an array which includes field names and an array which includes field values. I need to get class field by key from a dictionary and set value from dictionary to these fields and create new instance of this object
private static T test<T>(T obj, string[] fieldArr, string[] valueArr)
{
Type type = obj.GetType();
List<string> data = new List<string>();
var bindingFlags = BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.Public;
List<PropertyInfo> props = type.GetProperties(bindingFlags).ToList();
Dictionary<string, string> dict = new Dictionary<string, string>();
FieldInfo[] fieldInfos = type.GetFields();
for (int i = 0; i < fieldArr.Length; i++)
{
dict.Add(fieldArr[i], valueArr[i]);
}
var de = new List<PropertyInfo>();
foreach (var item in dict)
{
var fi = type.GetProperty(item.Key);
object obji = null;
fi.SetValue(obji, item.Value);
de.Add(fi);
}
return T;
}
Any suggestions?

How to map dictionary with values containg tuples to class instance

I have a dictionary of type Dictionary<string, (int Id, string Code, string Name)>:
var dict = new Dictionary<string, (int Id, string Code, string Name)>
{
["subjectType"] = (1, "1Code", "1Name"),
["residentType"] = (2, "2Code", "2Name"),
["businessType"] = (3, "3Code", "3Name"),
// and so on...
};
I use tuple (int Id, string Code, string Name) here but I can replace it with a class. So, it doesn't matter tuple or class, I just need to have three properties (Id, Code, Name) for each dictionary item.
I need to project this dictionary into a class, so I map each property of output model separately like this:
public static OutputModel Map(
Dictionary<string, (int Id, string Code, string Name)> dictionary) =>
new OutputModel
{
SubjectTypeId = dictionary["subjectType"].Id,
SubjectTypeCode = dictionary["subjectType"].Code,
SubjectTypeName = dictionary["subjectType"].Name,
ResidentTypeId = dictionary["residentType"].Id,
ResidentTypeCode = dictionary["residentType"].Code,
ResidentTypeName = dictionary["residentType"].Name,
BusinessTypeId = dictionary["businessType"].Id,
BusinessTypeCode = dictionary["businessType"].Code,
BusinessTypeName = dictionary["businessType"].Name,
// and so on...
};
I wonder is there any other (more fancy) way to do the same mapping?
You could do the following.
var outPutModel = new OutputModel();
foreach (var keyValuePair in dictionary)
outPutModel.Write(keyValuePair);
public class OutputModel
{
public void Write(KeyValuePair<string, (int Id, string Code, string Name)> keyValuePair)
{
var type = typeof(OutputModel);
type.GetProperty(keyValuePair.Key + "Id", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public).SetValue(this, keyValuePair.Value.Id);
type.GetProperty(keyValuePair.Key + "Code", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public).SetValue(this, keyValuePair.Value.Code);
type.GetProperty(keyValuePair.Key + "Name", BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public).SetValue(this, keyValuePair.Value.Name);
}
}
See it in action:
https://dotnetfiddle.net/jfKYsG

NHibernate AliasToBean transformer associations

I'm trying to use the following statement to get an entity with the fields I'm after:
retVal = session.CreateCriteria(typeof(MyEntity))
.CreateAlias("MyEntityProperty", "MyEntityProperty")
.Add(Restrictions.Eq("MyEntityProperty.Year", year))
.SetProjection(
Projections.Distinct(
Projections.ProjectionList()
.Add(Projections.Property("Property1"), "Property1")
.Add(Projections.Property("Property2"), "Property2")
.Add(Projections.Property("MyEntityProperty.RegisteredUser"), "MyEntityProperty.RegisteredUser")
.Add(Projections.Property("MyEntityProperty.CompanyInfo"), "MyEntityProperty.CompanyInfo")
)
)
.SetResultTransformer(Transformers.AliasToBean(typeof(MyEntity)))
.List<MyEntity>()
.Cast<BaseMyEntity>();
MyEntity is the entity I want to return, and MyEntityProperty is a property of MyEntity that is another entity (of type MyEntityProperty).
The error I get is Could not find a setter for property 'MyEntityProperty.RegisteredUser' in class 'MyEntity'
Is the AliasToBean transformer not able to handle sub entities? Or is there something more I need to do to make it work?
There is my master piece... which I'm using to transform any level of projections depth. Take it and use it like this:
.SetResultTransformer(new DeepTransformer<MyEntity>())
It could be used for any ValueType properties, many-to-one references and also for dynamic objects...
public class DeepTransformer<TEntity> : IResultTransformer
where TEntity : class
{
// rows iterator
public object TransformTuple(object[] tuple, string[] aliases)
{
var list = new List<string>(aliases);
var propertyAliases = new List<string>(list);
var complexAliases = new List<string>();
for(var i = 0; i < list.Count; i++)
{
var aliase = list[i];
// Aliase with the '.' represents complex IPersistentEntity chain
if (aliase.Contains('.'))
{
complexAliases.Add(aliase);
propertyAliases[i] = null;
}
}
// be smart use what is already available
// the standard properties string, valueTypes
var result = Transformers
.AliasToBean<TEntity>()
.TransformTuple(tuple, propertyAliases.ToArray());
TransformPersistentChain(tuple, complexAliases, result, list);
return result;
}
/// <summary>Iterates the Path Client.Address.City.Code </summary>
protected virtual void TransformPersistentChain(object[] tuple
, List<string> complexAliases, object result, List<string> list)
{
var entity = result as TEntity;
foreach (var aliase in complexAliases)
{
// the value in a tuple by index of current Aliase
var index = list.IndexOf(aliase);
var value = tuple[index];
if (value.IsNull())
{
continue;
}
// split the Path into separated parts
var parts = aliase.Split('.');
var name = parts[0];
var propertyInfo = entity.GetType()
.GetProperty(name, BindingFlags.NonPublic
| BindingFlags.Instance
| BindingFlags.Public);
object currentObject = entity;
var current = 1;
while (current < parts.Length)
{
name = parts[current];
object instance = propertyInfo.GetValue(currentObject);
if (instance.IsNull())
{
instance = Activator.CreateInstance(propertyInfo.PropertyType);
propertyInfo.SetValue(currentObject, instance);
}
propertyInfo = propertyInfo.PropertyType.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
currentObject = instance;
current++;
}
// even dynamic objects could be injected this way
var dictionary = currentObject as IDictionary;
if (dictionary.Is())
{
dictionary[name] = value;
}
else
{
propertyInfo.SetValue(currentObject, value);
}
}
}
// convert to DISTINCT list with populated Fields
public System.Collections.IList TransformList(System.Collections.IList collection)
{
var results = Transformers.AliasToBean<TEntity>().TransformList(collection);
return results;
}
}
Well wasn't I making things more complicated than necessary.
Instead of trying to set the fields on the sub entity, all I needed to do was reference the entity field itself:
.Add(Projections.Property("MyEntityProperty"), "MyEntityProperty")
and nHibernate populated it fine.
But I'm glad I asked because I got Radim's very useful code :-)

Same Variable Names - 2 Different Classes - How To Copy Values From One To Another - Reflection - C#

Without using AutoMapper... (because someone in charge of this project will shit bricks when they see dependencies)
I have a class (class A) with however many properties. I have another class (class B) with those same properties (same names and type). Class B could also have other un related variables.
Is there some simple reflection code that can copy values from class A to class B?
The simpler the better.
Type typeB = b.GetType();
foreach (PropertyInfo property in a.GetType().GetProperties())
{
if (!property.CanRead || (property.GetIndexParameters().Length > 0))
continue;
PropertyInfo other = typeB.GetProperty(property.Name);
if ((other != null) && (other.CanWrite))
other.SetValue(b, property.GetValue(a, null), null);
}
This?
static void Copy(object a, object b)
{
foreach (PropertyInfo propA in a.GetType().GetProperties())
{
PropertyInfo propB = b.GetType().GetProperty(propA.Name);
propB.SetValue(b, propA.GetValue(a, null), null);
}
}
If you will use it for more than one object then it may be useful to get mapper:
public static Action<TIn, TOut> GetMapper<TIn, TOut>()
{
var aProperties = typeof(TIn).GetProperties();
var bType = typeof (TOut);
var result = from aProperty in aProperties
let bProperty = bType.GetProperty(aProperty.Name)
where bProperty != null &&
aProperty.CanRead &&
bProperty.CanWrite
select new {
aGetter = aProperty.GetGetMethod(),
bSetter = bProperty.GetSetMethod()
};
return (a, b) =>
{
foreach (var properties in result)
{
var propertyValue = properties.aGetter.Invoke(a, null);
properties.bSetter.Invoke(b, new[] { propertyValue });
}
};
}
I know you asked for reflection code and It's an old post but I have a different suggestion and wanted to share it. It could be more faster than reflection.
You can serialize the input object to json string, then deserialize to output object. All the properties with same name will assign to new object's properties automatically.
var json = JsonConvert.SerializeObject(a);
var b = JsonConvert.DeserializeObject<T>(json);
Try this:-
PropertyInfo[] aProps = typeof(A).GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);
PropertyInfo[] bProps = typeof(B).GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);
foreach (PropertyInfo pi in aProps)
{
PropertyInfo infoObj = bProps.Where(info => info.Name == pi.Name).First();
if (infoObj != null)
{
infoObj.SetValue(second, pi.GetValue(first, null), null);
}
}

Saving a class to a delim file using reflection

I want to write the property names and matching data to a delimited file, I've copied some code from the c# objectdumper help file and it all seems to work OK but I dont understand reflection enough to be confident to use it. What I'm worried about is an incorrect value being placed in the incorrect column, is it possible for this to happen e.g.
Field1,Field2
Val1,Val2
Val1,Val2
Val2,Val1 << Could this ever happen ?
Also what does this piece of code mean?
f != null ? f.GetValue(this) : p.GetValue(this, null)
Code below:
public string returnRec(bool header, string delim)
{
string returnString = "";
bool propWritten = false;
MemberInfo[] members = this.GetType().GetMembers(BindingFlags.Public | BindingFlags.Instance);
foreach (MemberInfo m in members)
{
FieldInfo f = m as FieldInfo;
PropertyInfo p = m as PropertyInfo;
if (f != null || p != null)
{
if (propWritten)
{
returnString += delim;
}
else
{
propWritten = true;
}
if (header)
returnString += m.Name;
else
{
Type t = f != null ? f.FieldType : p.PropertyType;
if (t.IsValueType || t == typeof(string))
{
returnString += f != null ? f.GetValue(this) : p.GetValue(this, null);
}
}
}
}
return returnString;
}
Type t = f != null ? f.FieldType : p.PropertyType;
this is an inline if, asking is f != null then f.FieldType else p.PropertyType
can be written as
Type t;
if (f != null)
t = f.FieldType;
else
t = p.PropertyType;
#astander and #Frederik have essentially answered the questions and concerns that you specifically voiced, but I'd like to suggest doing things in a slightly more efficient manner. Depending on the number of object instances that you wish to write to your file, the method that you've presented may end up being quite inefficient. That's because you're gleaning type and value information via reflection on every iteration, which is unnecessary.
What you're looking for is something that looks up type information once, and then only uses reflection to get the value of properties and fields, e.g. (.NET 3.5),
public static IEnumerable<string> ReturnRecs(IEnumerable items, bool returnHeader, string delimiter)
{
bool haveFoundMembers = false;
bool haveOutputHeader = false;
PropertyInfo[] properties = null;
FieldInfo[] fields = null;
foreach (var item in items)
{
if (!haveFoundMembers)
{
Type type = item.GetType();
properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(pi => pi.PropertyType.IsValueType || pi.PropertyType == typeof (string)).ToArray();
fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance)
.Where(fi => fi.FieldType.IsValueType || fi.FieldType == typeof(string)).ToArray();
haveFoundMembers = true;
}
if (!haveOutputHeader)
{
yield return String.Join(delimiter, properties.Select(pi => pi.Name)
.Concat(fields.Select(pi => pi.Name)).ToArray());
haveOutputHeader = true;
}
yield return String.Join(delimiter,
properties.Select(pi => pi.GetValue(item, null).ToString())
.Concat(fields.Select(fi => fi.GetValue(item).ToString())).ToArray());
}
The above code only ever performs a GetProperties and GetFields once per group of records--also, because of this, there's no need to explicitly sort the properties and fields as was #Frederik's suggestion.
#astander has already given you an answer on the Type t = f != null ? f.FieldType : p.PropertyType; question, so I will leave that one out. Regarding getting the values into the correct columns, I don't know wheter reflection guarantees to list the members of a type in a specific order, but you can guarantee it by sorting the list before using it (using Linq):
MemberInfo[] members = typeof(Item).GetMembers(BindingFlags.Public | BindingFlags.Instance);
IEnumerable<MemberInfo> sortedMembers = members.OrderBy(m => m.Name);
foreach (MemberInfo member in sortedMembers)
{
// write info to file
}
Or if you prefer a non-Linq approach (works with .NET Framework 2.0):
MemberInfo[] members = typeof(Item).GetMembers(BindingFlags.Public | BindingFlags.Instance);
Array.Sort(members, delegate(MemberInfo x, MemberInfo y){
return x.Name.CompareTo(y.Name);
});
foreach (MemberInfo member in members)
{
// write info to file
}
Just to add some thoughts re the accepted answer, in particular for large data volumes:
PropertyInfo etc can be unnecessarily slow; there are ways to avoid this, for example using HyperDescriptor or other dynamic code
rather than building lots of intermediate strings, it may be more efficient to write output directly to a TextWriter
As a tweaked version that adopts these approaches, see below; note that I haven't enabled HyperDescriptor in this example, but that is just:
HyperTypeDescriptionProvider.Add(typeof(YourType));
Anyway...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
static class Program {
static void Main() { // just some test data...
var data = new[] { new { Foo = "abc", Bar = 123 }, new { Foo = "def", Bar = 456 } };
Write(data, Console.Out, true, "|");
}
public static void Write<T>(IEnumerable<T> items, TextWriter output, bool writeHeaders, string delimiter) {
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
foreach (T item in items) {
bool firstCol = true;
if (writeHeaders) {
foreach (PropertyDescriptor prop in properties) {
if (firstCol) {
firstCol = false;
} else {
output.Write(delimiter);
}
output.Write(prop.Name);
}
output.WriteLine();
writeHeaders = false;
firstCol = true;
}
foreach (PropertyDescriptor prop in properties) {
if (firstCol) {
firstCol = false;
} else {
output.Write(delimiter);
}
output.Write(prop.Converter.ConvertToString(prop.GetValue(item)));
}
output.WriteLine();
}
}
}

Categories