使用linq到sql进行反射 [英] using linq to sql with reflection

查看:68
本文介绍了使用linq到sql进行反射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

亲爱的所有人,
我有以下一种形式的代码,

Dear All,
I have following code for one type of form,

private void tuserBindingSource_CurrentChanged(object sender, EventArgs e)
     {

         var bs = sender as BindingSource;
         var cuser = bs.Current as database.tuser;
         using (var cont= new database .dbDataContext (context.Connection ))
         {
             var count=cont.tusers.Count(x => x.userid == cuser.userid);
             if (count > 0)
             {
                 useridTextBox.Enabled = false;
             }
             else
             {
                 useridTextBox.Enabled = true;
             }
         }
     }



我想要的是使用反射使代码通用.
任何人都可以建议如何做到这一点.我试图写
var count = cont.tusers.Count(x => x.userid == cuser.userid);使用gettype().它说不支持.
如果我成功做到这一点.会节省很多精力.
请帮忙.



What I want is to make the code generic using reflection .
Can anyone suggest how to do this. I tried to write
var count=cont.tusers.Count(x => x.userid == cuser.userid); using gettype() . It says it is not supported.
If I am successfull of doing this. it will save a lot of my efforts.
Please help.

推荐答案

对于某些事情,泛型是可以的,但对于其他事情则不是.试图使尺寸适合所有应用程序的尝试已多次失败.如您所知,在这种情况下,它不受支持.编译器需要先准备一些信息以构建正确的IL,而后期绑定则不提供这些信息.
Generics are OK for some things but not for others. Trying to make a one size fits all application has been attempted without success many times. In this case, as you found out, it is not supported. The compiler needs some information upfront to build the proper IL and late binding doesn''t provide that.


private static Expression<Func<TEntity,bool>> HasSameIdAsCurrentBindingSourceObject<TEntity,TId>(Expression<Func<TEntity,TId>> idPropertySelector, TEntity currentObject)
    where TEntity: class
{
    if(idPropertySelector==null)throw new ArgumentNullException("idPropertySelector");
    // compile the lambda expression parameter to a delegate
    Func<TEntity,TId> getIdentityProperty = idPropertySelector.Compile();
    // use the property delegate to get a reference to the identity property in the current scope
    TId currentId = getIdentityProperty(currentObject);
    // the make it into a ConstantExpression
    ConstantExpression currentIdConstant = Expression.Constant(currentId,typeof(TEntity));

    // extract the parameter from the lambda expression parameter
    ParameterExpression parameter = idPropertySelector.Parameters[0];
    // extract the identity accessor from the lambda expression parameter
    Expression theArgumentId = idPropertySelector.Body;

    // build the expression
    return Expression.Lambda<Func<TEntity,bool>>(Expression.Equal(theArgumentId,currentIdConstant),parameter);
}


private EventHandler CreateGenericBindingSourceChangedEventHandler<TEntity,TId>(Expression<Func<TEntity,TId>> idPropertySelector, Func<DataContext> openDataContext, TextBox textBox)
    where TEntity: class
{
    if(idPropertySelector==null)throw new ArgumentNullException("idPropertySelector");
    if(openDataContext==null)throw new ArgumentNullException("openDataContext");
    if(textBox == null)throw new ArgumentNullException("textbox");
    return (sender,e) => {
        var bindingSource = sender as BindingSource;
        if(sender==null)throw new InvalidOperationException();
        var currentBindingSourceObject = bindingSource.Current as TEntity;
        if(currentBindingSourceObject == null) throw new InvalidOperationException();

        using(var cont = openDataContext())
        {
            //  access the table using the generic GetTable instead of the DataContext property name.
            Table<TEntity> table = cont.GetTable<TEntity>();
            var theObjectHasTheSameIdAsTheCurrentBindingSourceObject = HasSameIdAsCurrentBindingSourceObject(idPropertySelector,currentBindingSourceObject);
            //  note that with your use case, you would get better performance with: table.Any(hasSameIdAsCurrentBindingSourceObject)
            var count = table.Count(theObjectHasTheSameIdAsTheCurrentBindingSourceObject);
            if(count>0)
            {
                textBox.Enabled = false;
            }
            else
            {
                textBox.Enabled = true;
            }
        }
    };
}


private void tuserBindingSource_CurrentChanged(object sender, EventArgs e)
{                    //  I am making the assumption your ID
     return          //  is an int.  change as necessary
     CreateGenericBindingSourceChangedEventHandler <database.tuser,int>
      (  x => x.userid==cuser.userid,
         () => new database.dbDataContext(context.Connection),
         userIdTextBox
      )(sender,e);

     // since this is all down to a single line, you are better off using this method in your statements where you are actually wiring up the event.  However, this shows how you could insert it directly into your existing code, by  invoking the EventHandler

     //  var bs = sender as BindingSource;
     //  var cuser = bs.Current as database.tuser;
     //  using (var cont= new database .dbDataContext (context.Connection ))
     //  {
     //      var count=cont.tusers.Count(x => x.userid == cuser.userid);
     //      if (count > 0)
     //      {
     //          useridTextBox.Enabled = false;
     //      }
     //      else
     //      {
     //          useridTextBox.Enabled = true;
     //      }
     //  }
}


这篇关于使用linq到sql进行反射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆