C# 如何防止MemberInfo.IsDefined在不相关的属性上引发FileNotFoundException?
我的项目使用类型C# 如何防止MemberInfo.IsDefined在不相关的属性上引发FileNotFoundException?,c#,.net,reflection,system.reflection,C#,.net,Reflection,System.reflection,我的项目使用类型SomeType引用TypesDefinitionAssembly,该类型由XSerializationLibrary中的属性XSerializationOptions和YSerializationOptions标记 显然,要检查SomeType是否由XSerializationOptions标记,我还需要参考XSerializationLibrary。但是,我不想引用YSerializationLibrary(它甚至可能不可用) 目前 typeof(SomeType).IsDe
SomeType
引用TypesDefinitionAssembly
,该类型由XSerializationLibrary
中的属性XSerializationOptions
和YSerializationOptions
标记
显然,要检查SomeType
是否由XSerializationOptions
标记,我还需要参考XSerializationLibrary
。但是,我不想引用YSerializationLibrary
(它甚至可能不可用)
目前
typeof(SomeType).IsDefined(typeof(XSerializationOptions))
失败,因为由于某种原因,IsDefined
,遍历所有属性并尝试解析其所有类型。例外情况如下所示:
System.IO.FileNotFoundException: Could not load file or assembly 'YSerializationLibrary, Version=1.2.3.4, Culture=neutral, PublicKeyToken=0123456789abcdef' or one of its dependencies. The system cannot find the file specified.
at System.ModuleHandle.ResolveType(RuntimeModule module, Int32 typeToken, IntPtr* typeInstArgs, Int32 typeInstCount, IntPtr* methodInstArgs, Int32 methodInstCount, ObjectHandleOnStack type)
at System.ModuleHandle.ResolveTypeHandleInternal(RuntimeModule module, Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
at System.ModuleHandle.ResolveTypeHandle(Int32 typeToken, RuntimeTypeHandle[] typeInstantiationContext, RuntimeTypeHandle[] methodInstantiationContext)
at System.Reflection.RuntimeModule.ResolveType(Int32 metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
at System.Reflection.CustomAttribute.FilterCustomAttributeRecord(CustomAttributeRecord caRecord, MetadataImport scope, Assembly& lastAptcaOkAssembly, RuntimeModule decoratedModule, MetadataToken decoratedToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, Object[] attributes, IList derivedAttributes, RuntimeType& attributeType, IRuntimeMethodInfo& ctor, Boolean& ctorHasParameters, Boolean& isVarArg)
at System.Reflection.CustomAttribute.IsCustomAttributeDefined(RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Int32 attributeCtorToken, Boolean mustBeInheritable)
at System.Reflection.CustomAttribute.IsDefined(RuntimeType type, RuntimeType caType, Boolean inherit)
有没有办法解决这个问题?如何检查XSerializationOptions
是否在SomeType
上定义,而不引用完全无关的yserizationlibrary
<> >一旦你认为<代码> XSerializationLibrary <代码>本身调用<代码> EnUM。因此,除非您在运行时无法访问Y库的非常特殊的情况下也引用了
YSerializationLibrary
,否则就不可能使用SomeType
对XSerializationLibrary
进行序列化,您可以尝试使用一个与您无权访问的具有相同名称和命名空间的新类来伪造该属性:
using System;
using System.Linq;
using ClassLibraryAssembly;
using OtherAssemblyX;
// This is a faking attribute, with same signature of that in unavailable assembly.
namespace OtherAssemblyY
{
public class YAttribute : Attribute
{
}
}
namespace MainAssembly
{
class Program
{
static void Main(string[] args)
{
var type = typeof (SomeType);
AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) =>
{
if (eventArgs.Name == "OtherAssemblyY, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")
return typeof(Program).Assembly;
return null;
};
Console.WriteLine(type.IsDefined(typeof (XAttribute), true));
foreach (var attrObject in type.GetCustomAttributes(true))
{
Console.WriteLine("Attribute found: {0}, Assembly: {1}", attrObject, attrObject.GetType().Assembly);
}
}
}
}
结果:
True
Attribute found: OtherAssemblyY.YAttribute, Assembly: MainAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Attribute found: OtherAssemblyX.XAttribute, Assembly: OtherAssemblyX, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
我不确定您最终想要实现什么,因为在运行时不加载程序集严重限制了您的能力,因为CLR类型解析器根据类型加载加载依赖程序集,撇开问题不谈,您可以使用Mono.Cecil检查属性是否定义,而不引用依赖程序集,甚至不存在依赖程序集 这是一个小样本 来自OptionX组件的MyX属性:
public class MyXAttribute:Attribute
{
public string TextX { get; set; }
}
public class MyYAttribute:Attribute
{
public string TextX { get; set; }
}
MyYatOptiony组件的属性:
public class MyXAttribute:Attribute
{
public string TextX { get; set; }
}
public class MyYAttribute:Attribute
{
public string TextX { get; set; }
}
TestC程序集中的MyClass:
(同时参考OptionX和OptionY组件)
主应用程序的解析器:
(没有对TestC、OptionX和OptionY程序集的任何引用,并且在解析期间OptionX和OptionY都不存在)
在不加载类型的情况下,如何检查它是否属于特定类型?这个问题对我来说毫无意义。如果更改应用属性的顺序,代码可能会工作(我不确定,这里是猜测)。但是,在没有被引用的dll的情况下运行程序是行不通的。@SriramSakthivel你说的是理论吗?理论上,我至少可以说,如果它是在不同的程序集中定义的,那么它肯定不是特定类型的;你甚至不需要检查类型名。我不会在没有DLL的情况下运行一个程序;然而,
IsDefined
要求我引用一个程序集,仅仅是因为我的程序永远不会使用某些其他属性,也不关心这些属性。我不明白你的意思。你能解释一下,如果不是特定的类型,你怎么能不用检查类型名就说出来?对我来说,这听起来像是一场灾难。你能解释一下你想解决什么问题吗?@SriramSakthivel请查看更新的问题。不过这并不是问题,依我所知。只要查看一下源代码,它似乎就获得了给定类型的所有属性(通过加载所有属性并检查类型),然后根据0
检查计数。他们本可以实施短路,但不幸的是,事实并非如此。所以你运气不好:(