Click here to Skip to main content
15,889,931 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Dear All,
I have following code for one type of form,
C#
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;
             }
         }
     }


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.
Posted

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.
 
Share this answer
 
C#
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;
     //      }
     //  }
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900