1.定義ATTRIBUTE
using System;
using System.Collections.Generic;
using System.Text;
namespace JasonNet.Platform.Common
...{
/**//// <summary>
/// <see cref="DefaultImplementationAttribute"/>標籤用於定義一個接口的默認實現類型。
/// </summary>
/// Title: DefaultImplementationAttribute
/// Author: 姜輝
/// Version: 1.0
/// History:
/// 2006-07-13 姜輝 [創建]
[AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class DefaultImplementationAttribute : Attribute
...{
private Type defaultImplementationType;
private string defaultImplementationTypeFullName;
/**//// <summary>
/// <see cref="DefaultImplementationAttribute"/>的構造函數。
/// </summary>
/// <param name="defaultImplementationType">指定接口的默認實現類型</param>
public DefaultImplementationAttribute(Type defaultImplementationType)
...{
this.defaultImplementationType = defaultImplementationType;
}
/**//// <summary>
/// <see cref="DefaultImplementationAttribute"/>的構造函數。
/// </summary>
/// <param name="defaultImplementationTypeFullName">指定接口的默認實現類型的字符串表達形式</param>
public DefaultImplementationAttribute(string defaultImplementationTypeFullName)
...{
this.defaultImplementationTypeFullName = defaultImplementationTypeFullName;
}
/**//// <summary>
/// 指定接口的默認實現類型。
/// </summary>
public Type DefaultImplementationType
...{
get
...{
return defaultImplementationType;
}
}
/**//// <summary>
/// 指定接口的默認實現類型的字符串表達形式。
/// </summary>
public string DefaultImplementationTypeFullName
...{
get
...{
return defaultImplementationTypeFullName;
}
}
}
}
2.定義構造容器類
using System.IO;
using System.Globalization;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Microsoft.Practices.ObjectBuilder;
using JasonNet.Platform.Common.Properties;
namespace JasonNet.Platform.Common
...{
/**//// <summary>
/// <see cref="ObjectContainer"/>用於創建、獲取容器中的對象實例。
/// Title: ObjectContainer
/// Author: 姜輝
/// Version: 1.0
/// History:
/// 2006-07-13 姜輝 [創建]
public static class ObjectContainer
...{
private static IBuilder<BuilderStage> builder = new Builder();
private static Locator locator = new Locator();
private const string InterfacePrefix = "I";
private const string AbstractClassPrefix = "Base";
private const string DefaultImplNamespaceSuffix = "DefaultImpl.";
/**//// <summary>
/// 根據指定的對象類型構造對象實例。
/// </summary>
/// <remarks>
/// <para>
/// <see cref="ObjectContainer"/>不支持簡單值類型的構造,因此,如果<typeparamref name="T"/>是簡單值類型,
/// 將拋出<see cref="ArgumentException"/>。
/// </para>
/// <para>
/// 如果<typeparamref name="T"/>是非靜態的實現類,則直接構建<typeparamref name="T"/>的對象實例。
/// </para>
/// <para>
/// 如果<typeparamref name="T"/>是接口或抽象類,則<see cref="ObjectContainer"/>將按以下規則來創建該接口
/// 或抽象類的實現類對象實例:
/// <list type="bullet">
/// <item>
/// <description>
/// 首先檢測<typeparamref name="T"/>是否標記了<see cref="DefaultImplementationAttribute"/>標籤來指定默認
/// 的實現類,如果指定了合法的默認實現類,則會構造出指定的默認實現類的對象實例;如果通過標籤指定的默認實
/// 現類不合法,則會拋出<see cref="TypeNotMatchException"/>或<see cref="DefaultImplementationNotFoundException"/>異常。
/// </description>
/// </item>
/// <item>
/// <description>
/// 如果<typeparamref name="T"/>沒有使用<see cref="DefaultImplementationAttribute"/>標籤來指定默認的實現
/// 類,則會根據<c>JasonNet</c>平臺默認的匹配關係(默認實現類的命名空間爲接口命名空間 + ".DefaultImpl",
/// 類名爲接口名稱去掉前綴“I”,或基類名稱去掉“Base”)來查找默認實現類,如果能夠找到,則構造出該默認
/// 實現類的對象實例,如果無法找到,則拋出<see cref="DefaultImplementationNotFoundException"/>異常。
/// </description>
/// </item>
/// </list>
/// </para>
/// <para>
/// 從以上對於接口或抽象類的默認實現對象的構造規則中可以看出,要成功構造一個接口或抽象類的默認實現類對象
/// ,需要滿足以下任意一項:
/// <list type="number">
/// <item>
/// <description>對<typeparamref name="T"/>使用<see cref="DefaultImplementationAttribute"/>進行了正確的
/// 配置,即<see cref="DefaultImplementationAttribute"/>指定的默認實現類確實實現了<typeparamref name="T"/>
/// 接口或抽象類。</description>
/// </item>
/// <item>
/// <description>
/// 如果<typeparamref name="T"/>沒有使用<see cref="DefaultImplementationAttribute"/>標籤來指定默認的實現
/// 類,則要求<typeparamref name="T"/>接口或抽象類、以及默認實現類的命名都遵循以下規範:1,接口必須以<c>
/// I</c>作前綴,抽象類必須以<c>Base</c>作前綴;2,默認實現類的命名空間爲接口命名空間 + ".DefaultImpl";
/// 3,默認實現類的名稱爲接口名稱去掉前綴“I”,或抽象類的名稱去掉前綴“Base”,如下例所示:
/// </description>
/// </item>
/// </list>
/// <example>
/// 以下是使用<see cref="DefaultImplementationAttribute"/>來配置接口與其默認實現類的示例,該情況下使用本
/// 方法傳入IUserManager接口可以構造出UserManager的實例。
/// <code>
/// namespace JasonNet.Platform.Security
/// {
/// [DefaultImplementation(typeof(JasonNet.Platform.Security.UserManager))]
/// public interface IUserManager {}
/// }
///
/// namespace JasonNet.Platform.Security
/// {
/// public class UserManager : IUserManager {}
/// }
/// </code>
/// 以下是使用<see cref="DefaultImplementationAttribute"/>來配置抽象類與其默認實現類的示例,該情況下使用
/// 本方法傳入BizLogDatabaseAdapter抽象類可以構造出基於SQL Server實現的SqlBizLogDatabaseAdapter的實例。
/// <code>
/// namespace JasonNet.Platform.Logging.Database
/// {
/// [DefaultImplementation(typeof(JaonNet.Platform.Logging.Database.SqlBizLogDatabaseAdapter))]
/// public abstract class BizLogDatabaseAdapter {}
/// }
///
/// namespace JasonNet.Platform.Logging.Database
/// {
/// public class SqlBizLogDatabaseAdapter : BizLogDatabaseAdapter {}
/// }
/// </code>
/// 以下是按<c>JasonNet平臺默認的匹配關係</c>定義的接口與其默認實現類的示例,該情況下使用本方法傳入
/// IUserManager接口可以構造出UserManager的實例。
/// <code>
/// namespace JasonNet.Platform.Security
/// {
/// public interface IUserManager {}
/// }
///
/// namespace JasonNet.Platform.Security.DefaultImpl
/// {
/// public class UserManager : IUserManager {}
/// } /// </code>
/// 以下是按<c>JasonNet平臺默認的匹配關係</c>定義的抽象類與其默認實現類的示例,該情況下使用本方法傳入
/// BaseBizLogDatabaseAdapter抽象類可以構造出BizLogDatabaseAdapter的實例。
/// <code>
/// namespace JasonNet.Platform.Logging.Database
/// {
/// public abstract class BaseBizLogDatabaseAdapter {}
/// }
///
/// namespace JasonNet.Platform.Logging.Database.DefaultImpl
/// {
/// public class BizLogDatabaseAdapter : BaseBizLogDatabaseAdapter {}
/// }
/// </code>
/// 以下是按<c>JasonNet</c>平臺爲解決工程間循環引用實現類的示例,該情況下使用本方法傳入
/// 指定接口的默認實現類型的字符串表達形式來構造出其實例。
/// <code>
/// namespace *****.****.DE.InnerInterfaces
/// {
/// [DefaultImplementation("*****.****.DE.DE.BusinessLogic.DesignProxyServiceFacade,*****.****.DE.BusinessLogic")]
/// public interface IDeDeInnerInterface
/// {
/// IList<String> GetDesignCompanyByProjectNo(string projectNo);
/// }
/// }
/// namespace *****.****.**.DE.InnerInterfaces
/// {
/// public interface IDesignProxyServiceFacade : IDeDeInnerInterface
/// {
/// 此處回到配置接口與其默認實現類的示例
/// }
/// </code>
/// </example>
/// </para>
/// <para>
/// 對於以上各種情況的實現類對象實例的創建,默認情況下,都將使用實現類的第一個構造函數來構造對象實例,
/// 如果第一個構造函數中含有參數,則對於簡單值類型以該類型的默認值爲參數值;對於對象類型,會在容器中去
/// 查找是否已經有該類型的對象存在,如果存在,則用該對象作爲參數值,如果不存在則構造一個新的該類型的對
/// 象作爲參數值(在構造該類型的對象時如果又需要參數,則類似地按上述步驟進行,即一層層地遞歸往下找,直
/// 到所有的依賴對象都被構造後,該對象纔會被構造)。由於帶參數的構造方式非常複雜,強烈建議使用不帶參數
/// 的構造函數來構造對象,即始終把不帶參數的構造函數放在代碼的最前面。
/// </para>
/// </remarks>
/// <typeparam name="T">要構造的對象的類型</typeparam>
/// <returns>構造的對象實例</returns>
/// <exception cref="ArgumentException">
/// 當<typeparamref name="T"/>是簡單值類型、或在T(或T的默認實現類)中無法找到構造所需的構造函數時拋出
/// 的異常。</exception>
/// <exception cref="TypeNotMatchException">
/// 當<typeparamref name="T"/>上的<see cref="DefaultImplementationAttribute"/>標籤所指定的默認實現類類
/// 型與<typeparamref name="T"/>不匹配(並沒有實現T或從T派生)時拋出的異常。</exception>
/// <exception cref="DefaultImplementationNotFoundException">
/// 當通過平臺默認的匹配關係無法找到<typeparamref name="T"/>的默認實現類時所拋出的異常。
/// </exception>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
public static T BuildUp<T>()
...{
return (T)BuildUp(typeof(T));
}
internal static object BuildUp(Type typeToBuild)
...{
Type reflectionType = null;
// typeToBuild 如果是值類型或者靜態類時
if (typeToBuild.IsValueType || (typeToBuild.IsAbstract && typeToBuild.IsSealed))
...{
throw new ArgumentException(
String.Format(CultureInfo.CurrentUICulture,
Resources.ExceptionTypeIsValueTypeOrStaticClass, typeToBuild.Name));
}
// typeToBuild是接口或抽象類
if (typeToBuild.IsAbstract)
...{
object[] defaultImplAttrs = typeToBuild.GetCustomAttributes(typeof(DefaultImplementationAttribute), false);
if (defaultImplAttrs.Length == 0)
...{
// 沒有標籤,按照默認規則尋找
// 如果類型的命名不符合規範,則拋出異常
if (!typeToBuild.Name.StartsWith(ObjectContainer.InterfacePrefix) &&
!typeToBuild.Name.StartsWith(ObjectContainer.AbstractClassPrefix))
...{
throw new IllegalTypeNameException(new string[] ...{ typeToBuild.FullName });
}
StringBuilder defaultImplTypeString = new StringBuilder();
defaultImplTypeString.Append(typeToBuild.FullName.Substring(0, typeToBuild.FullName.LastIndexOf(".") + 1));
defaultImplTypeString.Append(DefaultImplNamespaceSuffix);
if (typeToBuild.IsInterface)
...{
// 接口名稱去掉前綴“I”
defaultImplTypeString.Append(typeToBuild.Name.Substring(1));
}
else
...{
//抽象類的名稱去掉前綴“Base”
defaultImplTypeString.Append(typeToBuild.Name.Substring(4));
}
defaultImplTypeString.Append(", ");
defaultImplTypeString.Append(typeToBuild.Assembly.FullName);
reflectionType = SearchForTypeToBuild(defaultImplTypeString.ToString());
// 當沒有找到默認實現類
// 或者找到的是仍然是接口或者抽象類時
if (reflectionType == null ||
!typeToBuild.IsAssignableFrom(reflectionType) ||
reflectionType.IsAbstract ||
reflectionType.IsInterface)
...{
throw new DefaultImplementationNotFoundException(new string[] ...{ typeToBuild.FullName });
}
}
else
...{
// 有標籤 DefaultImplementationAttribute defImpl = defaultImplAttrs[0] as DefaultImplementationAttribute;
if (!String.IsNullOrEmpty(defImpl.DefaultImplementationTypeFullName))
...{
reflectionType = SearchForTypeToBuild(defImpl.DefaultImplementationTypeFullName);
}
else
...{
reflectionType = defImpl.DefaultImplementationType;
}
// 標籤所指定的默認實現類類型與typeToBuild不匹配(並沒有實現typeToBuild或從typeToBuild派生)
// 或者默認的實現也是一個接口或抽象類
if (reflectionType == null)
...{
throw new DefaultImplementationNotFoundException(new string[] ...{ typeToBuild.FullName });
}
if (reflectionType == typeToBuild ||
!typeToBuild.IsAssignableFrom(reflectionType) ||
reflectionType.IsAbstract ||
reflectionType.IsInterface)
...{
throw new TypeNotMatchException();
}
}
return builder.BuildUp(locator, reflectionType, null, null);
}
else
...{
// T是非靜態的實現類時,檢查其是否具有有效的構造函數
if (typeToBuild.GetConstructors().Length == 0)
...{
throw new ArgumentException(
String.Format(CultureInfo.CurrentUICulture,
Resources.ExceptionTypeHasNoConstructors, typeToBuild.Name));
}
return builder.BuildUp(locator, typeToBuild, null, null);
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
private static Type SearchForTypeToBuild(string defaultImplTypeString)
...{
Type reflectedType = null;
try
...{
reflectedType = Type.GetType(defaultImplTypeString);
}
catch
...{
}
return reflectedType;
}
}
}