1

I have an interface IDatabase that interfaces a few different ways to access a database. For example using RESTful, or MySqlDirectConnect.

Next I have a class foo that has member variables A, B, C that need to pull there data out of the database.

public class foo
{
    private string a;
    private int b;
    private int c;
}

Originally, I was going to create a Get method for every single member variable. Using Generics, you specify what interface you want to use.

public string GetA<T>() where T: IDatabase
{
   //example might be GetA<RESTful>();
}

public int GetB<T>() where T: IDatabase
{
   //example might be GetB<MySQL>();
}

and so on....

problem I see is that if the database changes I have to go back and change all these methods. In some cases class foo might have around 20 variables with a Get() method for each.

So I would like to create a really generic GetValue() where I can specify both the interface and the variable i would like to query for.

something along the lines of:

public object GetValue<T>(the class variable I want to query) where T: IDatabase
{
    //query database using type T and return it to the variable specified
}

I would like to avoid having a conditional for every member variable inside the method.

So is this possible?

4

3 回答 3

1

Generics don't seem like a good fit here at all. You want an interface IDatabase (as you have) which has multiple implementations: RestfulDb, MySqlDb, etc.

IDatabase can then have a method: object GetValue(string name) and you provide the concrete implementation of this in each class derived from IDatabase.

If you are using generics then how would your code in GetValue<T> know which instance of the MySql database you want to go after -- all it has is a type.

You might want to check out how a project like NHibernate deals with this.

于 2012-08-26T16:56:28.297 回答
0

Declare an interface :

public interface IDataProvider<T>
{
    T Get()
}

then implement one provider per data source and class type

public class FootRestProvider : IDataProvider<Foo>
{
    public Foo Get()
    {
        // implement logic to get foos from rest
     }
}

public class FooMySqlProvider : IDataProvider<Foo>
{
    public Foo Get()
    {
        // implement logic to get foos from mysql
    }
}   

Finally, if properties of Foo come from different sources; merge them in another class :

public class FooMerger
{
    // fill this list from constructor
    private IList<IDataProvider<Foo>> providers;

    public Foo Get()
    {
        var foosToMerge = providers.Select( x => x.Get() ).

        // implement merging logic here 
    }
}
于 2012-08-26T16:57:24.653 回答
0

Here is a great solution I worked out

public void GetValue<T>(string property) where T: IDatabase, new()
{
    IDatabase database = new T();
    database.RegisterObserver(this);

    string FROM = typeof(theCurrentClass).Name;
    string SELECT = editProperty = property;
    string WHERE = "1";

    database.Select(new Query(SELECT, FROM, WHERE));        
}

private string fieldName;  //contains the name of the field I want to edit

void IObserver.Update(object data)
{       
    FieldInfo field = this.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

    if(field != null)
    {
        field.SetValue(this, data);         
    }
}

EDIT: I finally figured it out, just updated the above code with the final answer

于 2012-08-26T20:13:56.473 回答