Skip to content

Instantly share code, notes, and snippets.

Created October 14, 2012 00:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/3886802 to your computer and use it in GitHub Desktop.
Save anonymous/3886802 to your computer and use it in GitHub Desktop.
Simple starting point for mapping key/value pairs to a dynamic type via reflection
/*
Copyright (c) 2010 - 2012 Jordan "Earlz/hckr83" Earls <http://lastyearswishes.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Reflection;
namespace ReflectionPrototype
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("Hello World!");
Dictionary<string, string> d=new Dictionary<string, string>();
d.Add("foo", "5821");
d.Add("Bar", "foobar!");
d.Add("Baz", "3295");
var tmp=new Tester();
ParameterFiller p=new ParameterFiller(d, tmp);
p.Fill();
Console.WriteLine(tmp.Foo);
Console.WriteLine(tmp.Bar);
Console.WriteLine(tmp.Baz);
Console.WriteLine(tmp.Foobar);
}
class Tester
{
[ParameterMap("foo")]
public int Foo{get;set;}
public string Bar{get;set;}
[ParameterIgnore()]
public int Baz{get;set;}
[ParameterDefault("foo!!!")]
public string Foobar{get;set;}
}
[AttributeUsage(AttributeTargets.Property)]
public class ParameterIgnoreAttribute : ParameterBaseAttribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class ParameterMapAttribute : ParameterBaseAttribute
{
public ParameterMapAttribute(string paramname)
{
name=paramname;
}
private string name;
public string Name{get{return name;}}
}
[AttributeUsage(AttributeTargets.Property)]
public class ParameterDefaultAttribute : ParameterBaseAttribute
{
public ParameterDefaultAttribute(object val)
{
value=val;
}
object value;
public object Value{get{return value;}}
}
public delegate object ParameterConverter(string val);
/*Attributes don't allow method arguments. TODO
* [AttributeUsage(AttributeTargets.Property)]
public class ParameterConverterAttribute : ParameterBaseAttribute
{
ParameterConverter Converter;
public ParameterConverterAttribute(ParameterConverter converter)
{
Converter=converter;
}
public object Convert(string val)
{
return Converter(val);
}
}*/
public abstract class ParameterBaseAttribute : Attribute
{
}
///<summary>
/// This class is will take a dictionary of parameters to values and will in turn take an object
/// and dynamically fill it in as appropriate using reflection. (hint: awesome!)
/// Only properties are supported right now
/// </summary>
public class ParameterFiller
{
IDictionary<string, string> Values;
public object Target{get{return target_;}}
object target_;
public ParameterFiller(IDictionary<string, string> values, object target)
{
target_=target;
Values=values;
}
public object Fill()
{
foreach(var p in Target.GetType().GetProperties())
{
MatchProperty(p);
}
return Target;
}
void MatchProperty(PropertyInfo p)
{
string matchname=p.Name;
object defaultval=null;
//ParameterConverterAttribute converter=null;
if(!p.CanWrite)
{
return; //don't bother if we can't do anything with this property
}
foreach(object attrib in Attribute.GetCustomAttributes(p, typeof(ParameterBaseAttribute), true))
{
if(attrib is ParameterIgnoreAttribute)
{
return; //exit if we need to ignore this property
}
else if(attrib is ParameterMapAttribute)
{
var tmp=(ParameterMapAttribute)attrib;
matchname=tmp.Name;
}else if(attrib is ParameterDefaultAttribute)
{
var tmp=(ParameterDefaultAttribute)attrib;
defaultval=tmp.Value;
}/*else if(attrib is ParameterConverterAttribute)
{
converter=(ParameterConverterAttribute)attrib;
}*/
}
if(!Values.ContainsKey(matchname))
{
if(defaultval!=null)
{
p.SetValue(Target, defaultval, null); //set to default if not found (and only if we have a default attribute)
}
return; //don't bother if we don't find a match
}
string val=Values[matchname];
/*if(converter!=null)
{
p.SetValue(Target, converter.Convert(val), null);
}*/
p.SetValue(Target, ConvertValue(val, p.PropertyType, defaultval), null);
}
object ConvertValue(string fromval, Type totype, object defaultval)
{
try
{
object tmp=Convert.ChangeType(fromval, totype);
if(tmp==null)
{
return defaultval;
}
return tmp;
}
catch
{
return defaultval;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment