• LiteMDA中支持Generic的BusinessObjectFactory实现


    在C# 2.0中提供了Generic支持,我们的Factory就也应该支持Generic,以下是我在LiteMDA的BusinessObjectFactory中的实现,同时支持Generic和非Generic的类。

    关于Interface及其对应的Assembly和Class的描述信息存在以下的BusinessObjectConfiguration.config中:
    <?xml version="1.0" encoding="utf-8"?>
    <BusinessObjectConfiguration>
      
    <xmlSerializerSection type="LiteMDA.Configuration.BusinessObjectConfiguration, LiteMDA.Configuration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        
    <BusinessObjectConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          
    <VisibleBusinessObjects>
            
    <BusinessObject>
              
    <InterfaceName>LiteMDA.BusinessObjectFactory.Test.ITestClass</InterfaceName>
              
    <Class AssemblyName="LiteMDA.BusinessObjectFactory.Test.exe" ClassName="LiteMDA.BusinessObjectFactory.Test.TestClass" />
            
    </BusinessObject>
            
    <BusinessObject>
              
    <InterfaceName>LiteMDA.BusinessObjectFactory.Test.IGenericTestClass`2[System.String,System.Object]</InterfaceName>
              
    <Class AssemblyName="LiteMDA.BusinessObjectFactory.Test.exe" ClassName="LiteMDA.BusinessObjectFactory.Test.GenericTestClass`2[System.String,System.Object]" />
            
    </BusinessObject>
            
    <BusinessObject>
              
    <InterfaceName>LiteMDA.BusinessObjectFactory.Test.ITestClass2</InterfaceName>
              
    <Class AssemblyName="LiteMDA.BusinessObjectFactory.Test.exe" ClassName="LiteMDA.BusinessObjectFactory.Test.GenericTestClass`2[System.String,System.Object]" />
            
    </BusinessObject>
          
    </VisibleBusinessObjects>
        
    </BusinessObjectConfiguration>
      
    </xmlSerializerSection>
    </BusinessObjectConfiguration>

    以上的Configuration中定义了三个可以被BusinessObjectFactory构造的类,构造时只需提供Interface,这里给出了三种典型的情况,一个是非Generic、一个是接口为Generic,类也为Generic,第三个是接口非Generic,类Generic。

    BusinessObjectFactory的源码如下:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Reflection;
    using LiteMDA.Configuration;
    using Microsoft.Practices.EnterpriseLibrary.Configuration;

    namespace LiteMDA.BusinessObjectFactory
    {
        
    /// <summary>
        
    /// ObjectFactory is the only gateway for creating Business Objects.
        
    /// </summary>

        public sealed class ObjectFactory
        
    {
            
    private ObjectFactory()
            
    {
            }


            
    /// <summary>
            
    /// _ObjectMap saves all the BOI/BO mapping pairs, this field will 
            
    /// be constructed from the BOI exposing configuration file at the 
            
    /// first time when the CreateObject method is invoked.
            
    /// </summary>

            private static BusinessObjectConfiguration _BOC = null;

            
    /// <summary>
            
    /// Create a Business Object.
            
    /// </summary>
            
    /// <typeparam name="TInterface">An exposed Business Object Interface.</typeparam>
            
    /// <returns>Return Business Object instance that implementing TInterface.</returns>
            
    /// <exception cref="LiteMDA.BusinessObjectFactory.InterfaceNotExposedException">
            
    ///    Thrown when the specified TInterface is not in the exposed interface list.
            
    /// </exception>
            
    /// <exception cref="LiteMDA.BusinessObjectFactory.ConfigurationFileFormatErrorException">
            
    ///    Thrown when the the format of the configuration file for BO/BOI mapping is error.
            
    /// </exception>

            public static TInterface CreateObject<TInterface>()
            
    {
                
    if (_BOC == null)
                
    {
                    
    // if this is the first time invoking CreateObject, load BOI/BO 
                    
    // mapping pairs from the configuration file first.
                    _BOC = ConfigurationManager.GetConfiguration("BusinessObjectConfiguration"as BusinessObjectConfiguration;
                }


                AssemblyClass ac 
    = _BOC[typeof(TInterface).ToString()];

                
    if (ac != null)
                
    {
                    
    //create object instance from the specified assemblyName and className
                    Assembly ass = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + ac.AssemblyName);
                    
    if (ac.ClassName.Contains("`"))
                    
    {
                        
    //It is a generic type, so fetch Type Parameters and bind then to the type before CreateInstance
                        Type t = ass.GetType(ac.ClassName.Substring(0, ac.ClassName.IndexOf("[")));
                        
    string typeParamListStr = ac.ClassName.Substring(ac.ClassName.IndexOf("["+ 1).TrimEnd(']');
                        
    string[] typeParamNames = typeParamListStr.Split(',');
                        Type[] typeParams 
    = new Type[typeParamNames.Length];
                        
    for (int i = 0; i < typeParamNames.Length; i++)
                        
    {
                            typeParams[i] 
    = Type.GetType(typeParamNames[i].Trim());
                        }

                        t 
    = t.MakeGenericType(typeParams);
                        
    return (TInterface)Activator.CreateInstance(t);
                    }

                    
    else
                    
    {
                        
    return (TInterface)ass.CreateInstance(ac.ClassName);
                    }

                }

                
    else
                
    {
                    
    throw new InterfaceNotExposedException(typeof(TInterface).ToString());
                }

            }

        }

    }


    几个测试类和接口代码如下:

    ITestClass.cs
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace LiteMDA.BusinessObjectFactory.Test
    {
        
    public interface ITestClass
        
    {
            
    void TestMethod();
        }

    }


    ITestClass2.cs
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace LiteMDA.BusinessObjectFactory.Test
    {
        
    public interface ITestClass2
        
    {
            
    void TestMethod2();
        }

    }


    IGenericTestClass.cs
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace LiteMDA.BusinessObjectFactory.Test
    {
        
    public interface IGenericTestClass<T, U>
        
    {
            
    void TestMethod();
        }

    }


    TestClass.cs
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace LiteMDA.BusinessObjectFactory.Test
    {
        
    public class TestClass : ITestClass
        
    {
            
    #region ITestClass Members

            
    public void TestMethod()
            
    {
                System.Windows.Forms.MessageBox.Show(
    "OK");
            }


            
    #endregion

        }

    }


    GenericTestClass.cs
    using System;
    using System.Collections.Generic;
    using System.Text;

    namespace LiteMDA.BusinessObjectFactory.Test
    {
        
    public class GenericTestClass<T, U> : IGenericTestClass<T, U>, ITestClass2
        
    {
            
    public void TestMethod()
            
    {
                System.Windows.Forms.MessageBox.Show(
    "OK2");
            }


            
    public void TestMethod2()
            
    {
                System.Windows.Forms.MessageBox.Show(
    "OK3");
            }

        }

    }


    测试代码如下:
            private void btnTestCreateBusinessObject_Click(object sender, EventArgs e)
            
    {
                ITestClass tc 
    = ObjectFactory.CreateObject<ITestClass>();
                tc.TestMethod();
                IGenericTestClass
    <stringobject> gtc = ObjectFactory.CreateObject<IGenericTestClass<stringobject>>();
                gtc.TestMethod();
                ITestClass2 tc2 
    = ObjectFactory.CreateObject<ITestClass2>();
                tc2.TestMethod2();

            }

    --
    顺便说一下,以上的Configuration使用EnterpriseLibrary读写的。在vs.net 2005 beta2中使用EntLib我费了一番波折才搞定,这里说以下怎样设置,免得大家再走弯路。

    你需要先用操作系统的搜索功能搜索entlib中src目录下所有包含"define VS2003"的.cs文件,大概十几个,把所有这些文件顶部的"VS2003"改成"VS2005B2",然后用vs.net 2005 beta2(vc#2005beta2也一样)打开EnterpriseLibrary.sln重新编译所有程序集,同时请使用重新编后的Enterprise Library Configuration Tool来建立Application的App.config或web.config。

    //文章结束
  • 相关阅读:
    Visual Studio 正则表达式替换
    NHibernate MappingException. No Persister
    C#枚举
    测试
    NHibernate & INotifyPropertyChanged
    NHibernate Profiler使用方法
    根据条件动态拼接LinQ的where条件字串
    wpf中ToolTip实现
    jquery的colorbox关闭并传递数据到父窗
    c#简易反射调用泛型方法
  • 原文地址:https://www.cnblogs.com/teddyma/p/211383.html
Copyright © 2020-2023  润新知