Wrapping an existing classes properties with nullable values

by Michael Henstock 30. January 2013 11:57

One of the things that I have needed to do recently was to take an existing class definition, clone it and turn all the value type properties into nullable definitions. We were doing this on some POCO with data obtained from our database, and needed to have a separate override object that we could default to the POCO data when null.

We created a generic class that would act as our wrapper with Set and Get methods to access the properties, with an expression parameter to strongly type the property name. I just used a simple dictionary as storage for the property values.
 
public class OverrideWrapper<TEntity>
{
    private Dictionary<string, object> _propertyStore = new Dictionary<string, object>();

    public Nullable<TValue> GetProperty<TValue>(Expression<Func<TEntity, TValue>> getter) where TValue : struct
    {
        return GetPropertyHelper<Nullable<TValue>, TValue>(getter);
    }

    public string GetProperty(Expression<Func<TEntity, string>> getter)
    {
        return GetPropertyHelper<string, string>(getter);
    }

    private TResult GetPropertyHelper<TResult, TValue>(Expression<Func<TEntity, TValue>> getter)
    {
        if (getter == null)
            throw new ArgumentNullException("getter");

        var propertyName = GetPropertyNameFromExpression(getter);

        return (TResult)GetProperty(propertyName);
    }

    private string GetPropertyNameFromExpression<TValue>(Expression<Func<TEntity, TValue>> exp)
    {
        var expression = (MemberExpression)exp.Body;

        // If we're accessing the Value property of a Nullable object, return the name of the Nullable property, not the Value property.
        if (expression.Expression != null &&
            expression.Expression is MemberExpression &&
            ((MemberExpression)expression.Expression).Type.GetGenericTypeDefinition() == typeof(Nullable<>))
        {
            return ((MemberExpression)expression.Expression).Member.Name;
        }
        else
        {
            return expression.Member.Name;
        }
    }

    public object GetProperty(string propertyName)
    {
        if (propertyName == null)
            throw new ArgumentNullException("propertyName");

        if (_propertyStore.ContainsKey(propertyName) && _propertyStore[propertyName] != null)
            return _propertyStore[propertyName];

        return null;
    }

    public void SetProperty<TValue>(Expression<Func<TEntity, TValue>> setter, TValue value) where TValue : struct
    {
        SetPropertyHelper(setter, value);
    }

    public void SetProperty(Expression<Func<TEntity, string>> setter, string value)
    {
        SetPropertyHelper(setter, value);
    }

    private void SetPropertyHelper<TValue>(Expression<Func<TEntity, TValue>> setter, TValue value)
    {
        if (setter == null)
            throw new ArgumentNullException("setter");

        var propertyName = GetPropertyNameFromExpression(setter);

        _propertyStore[propertyName] = value;
    }
}
We limited the properties to structs and strings hence the need for two overloaded methods, one for the generic structs and the other for the string properties.
 
A simple example of usage follows:
public class SampleObject
{
    public string StringProp { get; set; }
    public int IntProp { get; set; }
    public decimal DecimalProp { get; set; }
}

var test = new OverrideWapper<SampleObject>();

test.GetProperty(p => p.IntProp); // == null
test.GetProperty(p => p.StringProp); // == null

test.SetProperty(p => p.IntProp, 10);
test.SetProperty(p => p.StringProp, "set value");

test.GetProperty(p => p.IntProp); // == 10
test.GetProperty(p => p.StringProp); // == "set value"

Tags:

C#

Passing information to and from different plugins in CruiseControl.net

by Michael Henstock 8. January 2013 11:56

Passing a value from a custom trigger plugin to another plugin inside CruiseControl.net is quite simple.

From the ITrigger.Fire() method, CruiseControl.net expects an IntegrationRequest to be returned. In this object we can add the information that we wish to pass to our next plugin. To do this, we add our information to the BuildValues Dictionary<string, string> like this:
var request = new IntegrationRequest(buildCondition, "New integration request", null);
request.BuildValues.Add("my_info", "test info");
When a build is successfully started in CruiseControl.net, these values are parsed into the Parameters NameValuePair list on the IIntegrationResult object, that is either passed to your objects through the standard interface. This can be accessed like this:
var labelParameter = integrationResult.Parameters.SingleOrDefault(x => x.Name == "my_info");
if (labelParameter != null)
    return labelParameter.Value;

Tags:

C# | CruiseControl.net