小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

使用Fusion解析未引用的部分類型名稱

 碼農(nóng)9527 2021-04-29

最近,我的任務(wù)是編寫一個(gè)數(shù)據(jù)提取/報(bào)告框架,該框架將使客戶端應(yīng)用程序能夠定義要執(zhí)行的存儲(chǔ)過(guò)程,并將結(jié)果通過(guò)電子郵件發(fā)送給感興趣的各方。使該項(xiàng)目變得有趣的是允許用戶從一組查找表,Web服務(wù)數(shù)據(jù)和應(yīng)用程序派生數(shù)據(jù)中指定參數(shù)值的要求。在沒(méi)有任何外部引用的情況下,檢索Web服務(wù)或應(yīng)用程序派生數(shù)據(jù)的要求需要一種機(jī)制來(lái)執(zhí)行未引用程序集中的方法。

web

    本文概述了我的方法,該方法允許框架代碼通過(guò)部分類型名解析來(lái)執(zhí)行未引用程序集中的方法。

    問(wèn)題

    查找表數(shù)據(jù)的預(yù)填充非常簡(jiǎn)單-從表中選擇Id和Value字段-這是通過(guò)一個(gè)簡(jiǎn)單的ParameterLookup表實(shí)現(xiàn)的。但是,當(dāng)有時(shí)間用Web服務(wù)數(shù)據(jù)或特定于應(yīng)用程序的數(shù)據(jù)預(yù)先填充查找時(shí),我們需要某種機(jī)制來(lái)執(zhí)行客戶端應(yīng)用程序中的方法。在沒(méi)有對(duì)客戶端應(yīng)用程序的任何引用的情況下,我們需要一種機(jī)制來(lái)解析和執(zhí)行客戶端應(yīng)用程序代碼。我們實(shí)現(xiàn)的方法是LookupClass在ParameterLookup表中包含一個(gè)字段,并讓框架代碼解析類型并執(zhí)行該search方法。

    有許多常用的方法允許.NET代碼解析和執(zhí)行未引用類型的方法,盡管并非所有方法都適用于所有環(huán)境。當(dāng)宿主進(jìn)程是COM+進(jìn)程時(shí),Type.GetType()可以將調(diào)用與部分限定的類型名稱(即MyCompany.MyApplication.Search.Lookup.SomeLookup,MyCompany.MyApplication)一起使用。但是,當(dāng)主機(jī)進(jìn)程是IIS時(shí),必須指定完全限定的類型名稱(“類型名稱”,“程序集名稱”,“版本”,“區(qū)域性”,“公鑰”),或者該程序集必須存在于Web程序包的/bin目錄中。

    不希望ParameterLookup每次執(zhí)行新版本的應(yīng)用程序時(shí)都強(qiáng)制客戶端應(yīng)用程序更新表,我們需要一種僅使用Type和Assembly名稱部分的機(jī)制。

    解決方案

    如果您沒(méi)有完全限定的類型名稱(類型名稱,程序集類型,版本,區(qū)域性和公共密鑰),則在未引用的程序集中定義的類型可以是正確的PITA。

    例如,類型Microsoft.Build.BuildEngine.Engine類型的完全限定名稱為Microsoft.Build.BuildEngine.Engine,Microsoft.Build.Engine,Culture=neutral,Version=4.0.0.0,PublicKeyToken=b03f5f7f11d50a3a(真是令人討厭?。?。對(duì)于相對(duì)穩(wěn)定的組件,可以在配置表/文件中指定完全限定的類型名稱,但是對(duì)于版本號(hào)更改為相對(duì)不穩(wěn)定的不穩(wěn)定組件(例如,來(lái)自客戶端應(yīng)用程序的組件),您該怎么做?每個(gè)版本?

    Type.GetType()

    該Type.GetType()功能可用于加載在項(xiàng)目中引用或在程序集搜索路徑中的程序集。

Type t = Type.GetType("MyCompany.MyApplication.Lookup.SomeLookup, MyCompany.MyApplication "); 1復(fù)制代碼類型:[html]

    由于框架代碼不會(huì)引用該程序集,因此我們唯一的希望是該程序集位于程序集搜索路徑中。盡管這種情況是可能的,但肯定不能保證。

    該解決方案必須丟棄。

    如果我們?yōu)門ype.GetType()函數(shù)提供完全限定的類型名稱該怎么辦?

Type t = Type.GetType("MyCompany.MyApplication.Lookup.SomeLookup, 
  MyCompany.MyApplication, Culture=neutral, Version=1.0.0.3245, PublicKey= 1e9a8d893e3afa78");12復(fù)制代碼類型:[html]

    此調(diào)用肯定有效,并且類型引用已成功返回。所需要做的就是將此完全合格的類型傳遞給框架代碼-相對(duì)簡(jiǎn)單的練習(xí)。las,當(dāng)重新編譯程序集時(shí),將使用不同的內(nèi)部版本號(hào)(假定您使用的是內(nèi)部版本號(hào))創(chuàng)建該組件的新版本,該調(diào)用將返回原始程序集;否則,將返回原始程序集。不是更新的程序集。這是不理想的。

    該解決方案必須丟棄。

    我需要的是一種無(wú)需指定版本號(hào)或無(wú)需依靠程序集搜索路徑中的程序集即可解決類型的方法。

    Assembly.LoadFrom()

    該Assembly.LoadFrom()方法看起來(lái)很有希望,因?yàn)槲铱梢允褂么撕瘮?shù)來(lái)加載程序集而無(wú)論其位置如何,并遍歷該程序集中定義的每種類型。

internal static Type GetTypeFromAssembly(string assemblyName, string typeName)
{
 Assembly assembly = Assembly.LoadFrom(gacPath);
 Type[] types = assembly.GetTypes();
 
 foreach (Type type in types)
 {
  if (type.FullName == typeName))
   return type;
 }
 return null;
}123456789101112復(fù)制代碼類型:[html]

    條件if(type.FullName==typeName)使我們不必指定完全限定類型的版本,區(qū)域性或公鑰屬性?,F(xiàn)在,我們可以加載程序集并提取適當(dāng)?shù)念愋鸵怨┦褂谩?/p>

    但是,這導(dǎo)致了代碼和安裝實(shí)現(xiàn)之間的依賴性。如果支持操作員決定修改應(yīng)用程序安裝參數(shù),則可以將軟件安裝到未知位置??梢韵胂?,我們可能要求將軟件安裝到特定位置(例如ProgramFiles),但這會(huì)導(dǎo)致32位/64位問(wèn)題(ProgramFiles是指“ProgramFiles”還是“ProgramFiles(x86)”?)。

    但我想我快到了。

    融合

    如果將擁有我們所要類型的程序集安裝到全局程序集緩存中,則我們可以利用CLR程序集管理系統(tǒng)為我們加載并找到我們的程序集。

    使用Fusion.dll程序集(有關(guān)詳細(xì)信息,請(qǐng)參閱此鏈接),我們可以創(chuàng)建對(duì)適當(dāng)?shù)腉AC(32位或64位)的引用,并使用該Assembly.LoadFrom()方法安全地加載我們的程序集。

[DllImport("fusion.dll")]
internal static extern int CreateAssemblyCache(out IAssemblyCache ppAsmCache, int reserved);12復(fù)制代碼類型:[html]
private static string GetAssemblyPath(string name)
{
 if (name == null) 
  throw new ArgumentNullException("name");
 
 string finalName = name;
 AssemblyInfo aInfo = new AssemblyInfo();
 aInfo.cchBuf = 1024; // should be fine...
 aInfo.currentAssemblyPath = new String('\0', aInfo.cchBuf);
 
 IAssemblyCache ac;
 int hr = CreateAssemblyCache(out ac, 0);
 if (hr >= 0)
 {
  hr = ac.QueryAssemblyInfo(0, finalName, ref aInfo);
  if (hr < 0)
   return null;
 }
 
 return aInfo.currentAssemblyPath;
}123456789101112131415161718192021復(fù)制代碼類型:[html]
public static Type ResolveType(string assemblyName, string typeName)
{
 string gacPath = GetAssemblyPath(assemblyName);
 return GetTypeFromAssembly(assemblyName, typeName);
}12345復(fù)制代碼類型:[html]

    僅使用類型和程序集的名稱,代碼將搜索適合于應(yīng)用程序環(huán)境(x86/x64)的GAC目錄,并返回對(duì)該類型的引用。引用正確的類型后,對(duì)的調(diào)用Activator.CreateInstance()將創(chuàng)建要使用的可用類型。

    使用代碼

    框架定義了要解析的類型必須實(shí)現(xiàn)的接口。

namespace FrameworkApp
{
 public interface ILookup
 {
  string Search();
 }
}1234567復(fù)制代碼類型:[html]

    ...當(dāng)類實(shí)現(xiàn)接口時(shí)。

public class SearchType1 : ILookup
{
 public string Search()
 {
  return string.Format("SearchType1.Search() from version {0}", 
   Assembly.GetExecutingAssembly().GetName().Version);
 }
}12345678復(fù)制代碼類型:[html]

    現(xiàn)在,我們只需要調(diào)用TypeResolver.ResolveType(),創(chuàng)建一個(gè)返回類型的實(shí)例(強(qiáng)制進(jìn)入選擇的接口),最后執(zhí)行所需的方法。

Type type = TypeResolver.ResolveType("ClientApp.SearchType1,ClientApp");
ILookup lookup = Activator.CreateInstance(type) as ILookup;
lookup.Search();123復(fù)制代碼類型:[html]

    局限性

    程序集必須在GAC中注冊(cè)才能使此解決方案生效

    不會(huì)加載不兼容的.NET版本程序集

    將解析為最高版本,而不是最新編譯的版本

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多