C# 获取没有反射或已知类型的程序集引用

C# 获取没有反射或已知类型的程序集引用,c#,.net-4.0,xamarin.android,silverlight-5.0,C#,.net 4.0,Xamarin.android,Silverlight 5.0,在我当前的框架设计中,我仔细阅读了所有类型的特定程序集,并根据找到的类型进行工作。它搜索的程序集由应用程序引导程序/初始值设定项确定。程序集是在中编译的,因此可以通过:typeof(SomeTypeInTheAssembly.Assembly)对它们进行强引用。这很好,因为引导程序代码对程序集中的类型有很强的引用,并且不需要将完全限定名作为内联字符串,如果程序集限定名发生更改,则需要手动保持最新。但是我不喜欢在程序集中引用一些完全不相关的类型,并且依赖于该类型。(如果它移动到另一个程序集怎么办?

在我当前的框架设计中,我仔细阅读了所有类型的特定程序集,并根据找到的类型进行工作。它搜索的程序集由应用程序引导程序/初始值设定项确定。程序集是在中编译的,因此可以通过:
typeof(SomeTypeInTheAssembly.Assembly)对它们进行强引用。这很好,因为引导程序代码对程序集中的类型有很强的引用,并且不需要将完全限定名作为内联字符串,如果程序集限定名发生更改,则需要手动保持最新。但是我不喜欢在程序集中引用一些完全不相关的类型,并且依赖于该类型。(如果它移动到另一个程序集怎么办?如果我们弃用/删除该类型怎么办?更改其命名空间?)在代码中,它看起来也有点奇怪:

FrameworkAssemblyReader.Read(typeof(SomeAssemblyNamespace.SubNamespace.GraphingCalculator).Assembly);
现在在我的引导代码中,我对
GraphingCalculator
有一个直接的依赖关系(尽管是一个很小的依赖关系),它与引导阶段无关(作为一个GraphingCalculator,它当然与获取程序集引用无关)。为了避免这种情况,在我打算以这种方式使用的每个程序集中,我在它们的根中添加了一个类:

namespace SomeAssemblyNamespace
{
    public static class AssemblyReference
    {
        public static System.Reflection.Assembly Get
        {
            get
            {
                return typeof(AssemblyReference).Assembly;
            }
        }
    }
}
这并不太糟糕,因为我的引导代码如下所示:

FrameworkAssemblyReader.Read(SomeAssembly.AssemblyReference.Get);
但是现在,我有十几个左右的程序集使用这个
AssemblyReference
类复制/粘贴,我只希望随着应用程序在框架上构建,它会继续增长。因此,我的问题是,有没有一种好方法可以避免类重复,并且仍然以编程方式将程序集引用传递给基础框架,同时避免指向目标程序集中某个任意/不相关类型的模糊性?我的谷歌搜索似乎告诉我,没有API或语言特性可以让我强烈地指向程序集(比如类的
typeof
),但我希望这里有人能想出比我更好的解决方案,避免类/代码重复。同样值得注意的是,代码有时是针对Silverlight编译的,因此我知道这可能会限制一些API/技术。谢谢

编辑:为了添加另一个活动扳手,根据“TheCoon”的回答,我应该提到我并不总是加载相同的组件。例如,我可能有一个“CarBuilding”程序集,它适用于某些应用程序,但不是所有应用程序。由引导者告诉我他们希望使用哪一个(以及开发人员正在使用的任何定制的)

EDITx2:回答Jon Skeet的问题:客户(或我们内部)将创建他们希望支持其应用程序的任何项目/DLL。反过来,这些项目将参考内部基本框架。他们的项目可能包含资源(3D文件、图像、文本、本地化等)和插件类(他们实现了我们在应用程序生命周期中发现并实例化/执行的脚本)。此外,我们的系统还提供可选模块(DLL),其中包含可重用插件/内容,客户端(或我们)在制作特定应用程序时可以利用这些插件/内容。因此,您可能会看到如下项目结构:

Solution
    ->MyAppBootstrapper_Android
        ->MyAppGUI_Android
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Android

    ->MyAppBootstrapper_Silverlight
        ->MyAppGUI_Silverlight
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Silverlight
        ->BaseFrameworkGraphingModule
引导程序项目连接依赖项,并提供应向基础框架提供哪些项目/DLL(程序集)以进行发现。请注意,在本例中,“MyApp”在Android和Silverlight构建中共享自己的迷你框架和共享资源,但两者都有各自独立的引用。Silverlight one利用了
BaseFrameworkGraphingModule
,并且他们有自己特定于平台的资源

因此,项目中的引导程序看起来像(尽管简化了):

因此,对于构建在基本框架之上的每个应用程序,都会创建一个引导程序来指示要包括哪些程序集(以及其他一些不相关的布线工作)。为了明确回答这个问题,该项目对所需的每个程序集都有编译时引用(这需要双重职责,因为它确保所有DLL都打包在一起用于Android/Silverlight部署),因为它们不是动态下载到用户的智能手机或Silverlight应用程序,而是打包在初始下载中。关于引导程序如何知道要使用哪些程序集的问题,开发人员知道并放置必要的
FrameworkAssemblyReader.Read
调用。我希望这有帮助!谢谢你花时间看它。我有一种感觉,我什么都没做(或者错过了一个更好的解决方案/设计)

最后,我忽略了(愚蠢地)提到我们也针对Android的Mono进行编译,在不久的将来,还有WPF。温特很可能会成为未来的新成员,但我很乐意在我们到达这座桥时跨越这座桥。一般来说,由于每一个都是用自己的平台特性以自己的方式编译的,所以我并不介意不同的平台是否有不同的方式拉入程序集引用;不过如果平台之间有统一的语法就好了

EDITx3:是的,另一个。我提到了,但没有用一个例子说明不是所有的项目都需要或者应该被基本框架阅读。例如,实用程序或业务逻辑项目的代码与基本框架无关,但与客户端应用程序相关。从上面的例子来看:

Solution
    ->MyAppBootstrapper_Android
        ->MyAppGUI_Android
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Android
        ->MyCompanySharedUtilities

    ->MyAppBootstrapper_Silverlight
        ->MyAppGUI_Silverlight
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Silverlight
        ->BaseFrameworkGraphingModule
        ->MyCompanySharedUtilities

MyAppGUI\u Silverlight和MyAppFramework可以利用MyCompanySharedUtilities的
MyCompanySharedUtilities
,但开发人员可能不会通过
FrameworkAssemblyReader运行它。请阅读
,因为它只包含一些数学的专有实现,或者业务规则。

我不确定您希望您的客户如何使用此代码,因此此建议可能与此无关,但取消设置功能(在
Solution
    ->MyAppBootstrapper_Android
        ->MyAppGUI_Android
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Android
        ->MyCompanySharedUtilities

    ->MyAppBootstrapper_Silverlight
        ->MyAppGUI_Silverlight
        ->MyAppFramework
        ->MyAppResources
        ->MyAppAdditionalResources_Silverlight
        ->BaseFrameworkGraphingModule
        ->MyCompanySharedUtilities
<ReferencedAssemblies>
    <ReferencedAssembly key="UnchangingKey" qualifiedName="SomeAssemblyName, version=1.0.0.0, Culture=neutral, PublicKeyToken=0123456789abcdef" />
</ReferencedAssemblies>
<ItemGroup>
  <Reference Include="System.Core">
    <RequiredTargetFramework>3.5</RequiredTargetFramework>
  </Reference>
  <Reference Include="System.Drawing" />
  <Reference Include="System.Windows.Forms" />
  <Reference Include="System.Xml.Linq">
    <RequiredTargetFramework>3.5</RequiredTargetFramework>
  </Reference>
  <Reference Include="System.Data.DataSetExtensions">
    <RequiredTargetFramework>3.5</RequiredTargetFramework>
  </Reference>
  <Reference Include="UIAutomationProvider">
    <RequiredTargetFramework>3.0</RequiredTargetFramework>
  </Reference>
  <Reference Include="WindowsBase">
    <RequiredTargetFramework>3.0</RequiredTargetFramework>
  </Reference>
  <Reference Include="PresentationCore">
    <RequiredTargetFramework>3.0</RequiredTargetFramework>
  </Reference>
  <Reference Include="PresentationFramework">
    <RequiredTargetFramework>3.0</RequiredTargetFramework>
  </Reference>
  <Reference Include="System" />
  <Reference Include="System.Data" />
  <Reference Include="System.Xml" />
</ItemGroup>