开发者

Is this an appropriate use of generics and C#'s dynamic data type?

开发者 https://www.devze.com 2023-03-19 18:38 出处:网络
The problem I\'m having is thus, we\'re building a data access layer using our existing ORM (it\'s an old one called Gentle) with the idea of moving to something like Fluent NHibernate. There are a fe

The problem I'm having is thus, we're building a data access layer using our existing ORM (it's an old one called Gentle) with the idea of moving to something like Fluent NHibernate. There are a few queries where we have to add custom clauses to the SqlBuilder in our existing setup, so for instance when retrieving some person objects we might be adding a clause like:

"PersonId in (SELECT PersonId from Orders where OrderValue > " + orderValue + " and OrderName = " + orderName

The point being that the parameters are being added directly in a string rather than as a parameterised query, it is possible in Gentle to add it as a parameterised query and this is what I've been working on. All our DALs inherit from a base GentleDAL, this is the class that actually constructs the Gentle query, adds the clauses and parameters etc. To add a parameterised clause in Gentle you have to do two things with your SqlBuilder object, you have to call sb.AddConstraint(string clause) to add your clause, and then for each parameter you have to call sb.AddParameter(string name, Type type), you can then construct your SqlStatement object from this, and only after that can you set the value for your parameter where you call stmt.SetParameter(string name, object value).

The way I have represented these parameters/clauses is I have created a class called GentleClauseCollection, this contains the clauses and parameters and has Add and Get methods for both of these things. Clauses are just strings and are stored internally in a List, the parameters are stored in a GentleParameter class which uses generics. The full code for GentleParameter is as follows.

public class GentleParameter<TParamType>
{       
    public string Name { get; private set; }
    public TParamType Value { get; private set; }
    public Type ParameterType  {get { return typeof (TParamType); }}
    public GentleParameter(string parameterName, TParamType parameterValue)
    {
        Name = parameterName;
        Value = parameterValue;
    }
}

There is no collection in .NET that I'm aware of that would let me store GentleParameter for different values of TParamType in the same collection, however it can be done using the DLR. In my GentleCollection class I store the parameters in a List and I get the parameters from this class as an IEnumerable. The Add method in my class is able to only allow GentleParameter's to be added so I know that开发者_StackOverflow my parameters will always have a Name, Value and ParameterType field which I can access.

My questions are: Given I could sacrifice the generics and change my parameter class Value property to be 'object' instead of T, have I overcomplicated things by using dynamic, what are the pros and cons of both approaches? Is there a third way to do this that I haven't thought of and how significant a performance impact am I likely to see by using dynamic given that all the method calls using the dynamic objects will be compiled at run time?

Thanks in advance for your help.


As sb.SetParameter is not generic and awaits an object, I would not make GentleParameter generic and hence I would not use the DLR.


Using dynamic doesn't seem over complicated to me. Method calls are resolved at runtime and it's cached the resulting invocation probably averages about 10x slower (we are talking nanoseconds). So it depends on how you are going to use it if it makes sense.

If you are always going to use it as type Object than yes you don't need to be using type dynamic not that it would have hurt anything.

If you want to be able to access properties than yes you should use dynamic, the result code will look cleaner than anything else you could do.

But even using dynamic you don't necessarily have to call the properties themselves dynamically, if you want to have as much static typing is possible you can have dynamic resolve a helper method that takes a generic form of your GentleParameter and do your work inside that.

 ...

private void HelperDoStuffWithGenericParam<T>(GentleParameter<T>param){

        //Do stuff you have the static typing
}
0

精彩评论

暂无评论...
验证码 换一张
取 消