tags:

views:

188

answers:

5

Hi,I want to build a form entity, which should contain form form fields

so: i want to have a class that looks something like this:

public abstract class form {
public string FormName;
public IList<FormField> Fields;
}

i want my FormField class to have one method: getValue.

But, i want it to be generic, so getValue would not return an Object but the actual value of the object..

Any suggestions?

+1  A: 

public abstract class Form<T>{
  public string FormName;
  public IList<FormField<T>> Fields;
}

public class FormField<T>{
  public T getValue { ... code here ...  }
}
Derick Bailey
That means my form will only contain,for example string fields, but thats not what i want, i want to be able for it to contain many diffrent types of fields.
MindFold
@MindFold: I've modified this solution using an interface to accomplish what you're looking for.
recursive
+2  A: 

This will work:

public abstract class Form<T>{
  public string FormName;
  public IList<IFormField> Fields;
}

public class FormField<T> : IFormField{
    public T getValue() { return default(T); }

    object IFormField.getValue() {  
        return this.getValue();
    }
}

public interface IFormField { 
      object getValue();
}
recursive
This will work, but again, this will not ensure that i'll have the GetValue method on each item inside the list, this is more of a workaround then a solution.
MindFold
@MindFold: I've added a getValue method to the interface which should address that problem.
recursive
mmm, how that will work? will it return me an Object or the T?
MindFold
@Mindfold: I've corrected some syntax errors, but will return the instance of T, cast as an object, which is really the best you can possibly hope for, given that `Fields` contains multiple types of T.
recursive
+1  A: 
public abstract class Form {
    public IList<FormField> Fields;
    public string FormName;
}

public class FormField {
    private Object field;

    public T getValue<T>() {
        return (T) field;
    }
}
DreamWalker
+2  A: 

Unfortunately there is no way to create a single generic list containing objects, that each have a different return type for a given method, like the one you want.

The best you can do is an interface, or base class, and a method that returns Object.

This means you will have to cast, but then, you would have to do that anyway.

How would this code work if you could have different return types:

FormField f = _Fields[0];
?? x = f.GetValue();
Lasse V. Karlsen
hmmm, i think your right there, i thought something along the lines of the var, but from what i understand thats just a syntactic sugar in c#
MindFold
Correct, "var" is not dynamic, you might be able to do this with the dynamic keyword (at least from the "var" point of view), but you would still not be able to have differing return types. I would take your code two steps back and try to see if there is a different way to accomplish your goals.
Lasse V. Karlsen
Is there any other good way to implement this, so you're saying i must give up on explicit type checking?
MindFold
Sunny
In order to have type checking, you need to be able to determine what the types of all the expressions are in advance. Under the scheme you're proposing, there is no way to do that, so what would actually be checked?
recursive
+1  A: 

Please see the complete code below. My solution works like:

var myForm = new Form();
var int_value = myForm.Fields
           .OfType<IntegerFormField>()
           .First(c => c.Name == "c1").GetValue();
var decimal_value = myForm.Fields
           .OfType<DecimalFormField>()
           .First(c => c.Name == "c2").GetValue();

The field interfaces:

    public interface IFormField
    {
        object GetValue();
        string Name { get; }
    }

    public interface IFormField<T> : IFormField
    {
        T GetValue();

    }

The abstract base class for all form fields:

abstract class FormFieldBase<T> : IFormField<T>
        {
            private readonly T _value;

            public FormFieldBase(T value, string name)
            {
                _value = value;
                Name = name;
            }

            #region IFormField<T> Members

            public virtual T GetValue()
            {
                return _value;
            }

            #endregion

            #region IFormField Members

            object IFormField.GetValue()
            {
                return _value;
            }

            public string Name { get; private set; }

            #endregion
        }

Two sample form field implementation:

class IntegerFormField : FormFieldBase<int>
{
     public IntegerFormField(int value, string name) : base(value, name) { }
}

class DecimalFormField : FormFieldBase<decimal>
{
     public DecimalFormField(Decimal value, string name) : base(value, name) { }
}

The Form Class:

class Form
    {
        public IList<IFormField> Fields
        {
            get
            {
                return new List<IFormField>(){
                        new IntegerFormField(10, "c1"), 
new DecimalFormField(200, "c2")
                 };
            }
        }
    }

HTH

Sunny