views:

108

answers:

2

I want to create a generalized helper method for LoadFromXML loading and validation. If the XML I'm loading from is incomplete, I do want it to fail completely without throwing an exception. Currently, my code looks like this (more or less)

public override bool Load(XElement source)
{
    return new List<Func<XElement, bool>>
    {
        i => this.LoadHelper(i.Element(User.XML_Username), ref this._username, User.Failure_Username),
        i => this.LoadHelper(i.Element(User.XML_Password), ref this._password, User.Failure_Password)
        //there are many more invokations of LoadHelper to justify this architecture
    }
    .AsParallel()
    .All(i => i.Invoke(source));
}

private bool LoadHelper(XElement k, ref string index, string failure)
{
    if (k != null && k.Value != failure)
    {
        index = k.Value;
        return true;
    }
    return false;
}

this._username is a private member variable that is used by the property this.Username. This is the current solution I have for this problem, but I'm facing one major issue: Since I cannot pass the property itself to the LoadHelper and Action<string> doesn't match the property :(, I'm circumventing the property setter logic right now.

For your own musings, before the LoadHelper abstraction, each of my List<Func<XElement, bool>>'s entries looked like this...

i => ((Func<XElement, bool>)(k => { if (k == null || k.Value == User.Failure_Username) return false; 
                    { this.Username = k.Value; return true; } })).Invoke(i.Element(User.XML_Username)),

Question: Does anyone know any way to do this without circumventing the property's setter logic?

+3  A: 

Action doesn't match the property

If I read that right, you tried replacing the "ref string index", with "Action<string>" and then tried passing the Protperty. Close but not quite. How 'bout?

private bool LoadHelper(XElement k, Action<string> setter, string failure) 
{ 
    if (k != null && k.Value != failure) 
    { 
        setter(k.Value); 
        return true; 
    } 
    return false; 
} 

then

  i => this.LoadHelper(i.Element(User.XML_Username), s=>{this.Username = s},
                          User.Failure_Username),     
James Curran
Wow. Yes, you got it. This is it! Thanks a ton mate!
Legatou
Isn't it a shame that you can't treat properties in a first-class way as `Action<T>` or `Func<T>` delegates? Definitely one of my most irritating sticking points about C#.
mquander
I couldn't agree more. I understand why -- C# would have to infer a little too much about the parameter (whether it's an Action<T> or Func<T>) for how statically typed C# is. But still... We should petition Microsoft to change this! :D
Legatou
A: 

I've sometimes wondered how much it would bloat things for .Net to support an iProperty(of T) interface with two members, Get and Set, and automatically wrap fields and properties so that an iProperty(of T) parameter could be passed a field or property.

Using anonymous methods, one could create such a thing not too totally horribly by creating an xProperty class whose constructor took the methods necessary to get and set a property. One could define instances of the class for any properties that one wanted other classes to be able to manipulate directly. Things would be much nicer, though, if there were a standard interface. Unfortunately, I'm unaware of one existing.

supercat