简体   繁体   English

在C#中使用泛型

[英]using Generics in C#

I have started looking into using generics in C#. 我已经开始研究在C#中使用泛型。 As an example what i have done is that I have an abstract class which implements generic methods. 作为一个例子,我所做的是我有一个实现通用方法的抽象类。 these generic methods take a sql query, a connection string and the Type T as parameters and then construct the data set, populate the object and return it back. 这些通用方法以sql查询,连接字符串和Type T作为参数,然后构造数据集,填充对象并将其返回。 This way each business object does not need to have a method to populate it with data or construct its data set. 这样,每个业务对象都不需要具有使用数据填充它或构造其数据集的方法。 All we need to do is pass the type, the sql query and the connection string and these methods do the rest.I am providing the code sample here. 我们需要做的就是传递类型,sql查询和连接字符串,其余方法由这些方法完成。我在这里提供代码示例。 I am just looking to discuss with people who might have a better solution to what i have done. 我只是想与可能对我所做的事情有更好解决方案的人们讨论。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using MWTWorkUnitMgmtLib.Business;
using System.Collections.ObjectModel;
using System.Reflection;

namespace MWTWorkUnitMgmtLib.TableGateway
{
    public abstract class TableGateway
    {
        public TableGateway()
        {

        }

        protected abstract string GetConnection();
        protected abstract string GetTableName();

        public DataSet GetDataSetFromSql(string connectionString, string sql)
        {
            DataSet ds = null;
            using (SqlConnection connection = new SqlConnection(connectionString))
            using (SqlCommand command = connection.CreateCommand())
            {
                command.CommandText = sql;
                connection.Open();
                using (ds = new DataSet())
                using (SqlDataAdapter adapter = new SqlDataAdapter(command))
                {
                    adapter.Fill(ds);
                }
            }
            return ds;
        }

        public static bool ContainsColumnName(DataRow dr, string columnName)
        {
            return dr.Table.Columns.Contains(columnName); 
        }

        public DataTable GetDataTable(string connString, string sql)
        {
            DataSet ds = GetDataSetFromSql(connString, sql);
            DataTable dt = null;
            if (ds != null)
            {
                if (ds.Tables.Count > 0)
                {
                    dt = ds.Tables[0];
                }
            }
            return dt; 
        }

        public T Construct<T>(DataRow dr, T t) where T : class, new()
        {
            Type t1 = t.GetType();
            PropertyInfo[] properties = t1.GetProperties();

            foreach (PropertyInfo property in properties)
            {
                if (ContainsColumnName(dr, property.Name) && (dr[property.Name] != null))
                    property.SetValue(t, dr[property.Name], null); 
            }

            return t; 
        }

        public T GetByID<T>(string connString, string sql, T t) where T : class, new()
        {
            DataTable dt = GetDataTable(connString, sql);
            DataRow dr = dt.Rows[0];
            return Construct(dr, t); 
        }

        public List<T> GetAll<T>(string connString, string sql, T t) where T : class, new()
        {
            List<T> collection = new List<T>();
            DataTable dt = GetDataTable(connString, sql);
            foreach (DataRow dr in dt.Rows)
                collection.Add(Construct(dr, t));

            return collection; 
        }
    }
}

You can improve perfs by generating and caching delegates to set properties: 您可以通过生成和缓存用于设置属性的委托来提高性能:

public static class Utils
{
        public static Action<T, object> MethodDelegateFor<T>(MethodInfo method)
        {
            var parameter = method.GetParameters().Single();
            var instance = Expression.Parameter(typeof(T), "instance");
            var argument = Expression.Parameter(typeof(object), "argument");
            var methodCall = Expression.Call(
                instance,
                method,
                Expression.Convert(argument, parameter.ParameterType)
                );
            return Expression.Lambda<Action<T, object>>(
                methodCall,
                instance, argument
                ).Compile();
        }

        public static Action<T, object> PropertySetterFor<T>(PropertyInfo property)
        {
            return MethodDelegateFor<T>(property.GetSetMethod());
        }
}

usage: 用法:

var propSetter = Utils.PropertySetterFor<T>(yourPropInfo);
propSetter(newInstance, theValue);

It would be more powerful, I believe, to use the unit of work pattern, with the repository pattern, but modified to a generic example. 我相信,将工作单元模式与存储库模式一起使用会更强大,但可以修改为通用示例。

Then you could build a fully functioning CRUD, with Polymorphism for "special" things, you need your specializations to do. 然后,您可以构建功能全面的CRUD,并针对“特殊”事物使用多态性,您需要进行专业化处理。

Would also switch out the old SQL command with entity framework. 还将使用实体框架切换旧的SQL命令。 would lighten your workload considerably. 会大大减轻您的工作量。

That is what I would do. 那就是我会做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM