2012-06-12 17 views
0

我有一个项目,其中SGEN用于预编译序列化程序集(不带/ proxytypes标志)。在这个项目中,生活到目前为止一直是内部的课程(因此sgen将离开它)。我需要公开课程,而这样做的简单行为会导致sgen失败,并显示错误:SGEN公共泛型方法的where子句失败

类型'Infragistics.Shared.DisposableObject'在未引用的程序集中定义...'

这个程序集确实被引用了,并且总是有,否则程序集本身不会编译。版本也完全匹配,并且引用已关闭特定版本。

第一个令人困惑的部分是这个类没有公共状态(没有公共字段,根本没有属性),这并没有使它成为序列化的好候选者。

更容易混淆的部分是,删除one-and-only公共(通用)方法中的where子句允许sgen处理程序集就好了。

这里是唯一的公共类,它不显式实现的事情(有该接口,没有相关实现了两个方法):

public class AppointmentDrawFilter : IUIElementDrawFilter 
{ 
    // This is a fluent method to register a type with its handler 
    public AppointmentDrawFilter Support<TUiElement>(DrawPhase phases, Func<UIElement, Appointment> retriever = null) 
     where TUiElement : UIElement // <-- commenting out (or changing UIElement to MarshalByRefObject) fixes sgen 
    { 
     // adds input to a couple dictionaries (failure still occurs with body commented out) 
     return this; 
    } 
} 

注:的UIElement从DisposableObject继承,类型那sgen在失败时找不到。请注意,当我注释掉where子句时,UIElement仍在其他地方使用,但sgen并不感到不快。标记内部的Support()方法也允许sgen完成,因为它只关心公共资料。

为什么sgen会首先关心非webservices公共方法?

为什么它只会在where子句的存在上绊倒?

为什么在这个特殊情况下sgen没有发现组件,当它明显存在时?

回答

1

我做了一些测试,并找到了一个可能的解决方法,您可以使用。

我发现,如果您有一个通用方法,该通用方法具有aa where子句,该子句从您没有的程序集中引用某个类型(或由where子句引用的类型的基本类型)在当前程序集中派生的任何类型。

例如,我发现这个问题的简单再生产是:

类库一个与下面的C#代码:

namespace One 
{ 
    public class BaseObject 
    { 
    } 
} 

类库两个与下面的C#代码:

using One; 

namespace Two 
{ 
    public class TestClass 
    { 
     public void TestMethod<T>() 
      where T : BaseObject 
     { 

     }   
    } 
} 

在Two.dll上使用sgen时,错误被重现,它抱怨程序集没有被引用。

对于解决方法,我发现我可以在汇编(类库)中派生任何类两个从汇编中的类一个或实现从汇编一个接口。要在特定的情况下,解决这个你可以添加以下类:

using Infragistics.Shared; 
namespace DayViewTextCenter 
{ 
    public class WorkaroundSgenIssue:DisposableObject 
    { 
     protected override void OnDispose() 
     { 
     } 
    } 
} 

虽然我实际上并没有找到答案,你问了三个问题,我也发现,实际的错误是一个System.InvalidOperationException在编译System.Xml.Serialization.Compiler类的方法:

System.InvalidOperationException occurred 
    Message=Unable to generate a temporary class (result=1). 
error CS0012: The type 'One.BaseObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'One, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. 

    Source=System.Xml 
    StackTrace: 
     at System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence) 
    InnerException: 

我能够从上面和使用以下代码重现此引用组件一和二:

Type type = typeof(TestClass); 
Assembly assembly = type.Assembly; 
XmlReflectionImporter importer = new XmlReflectionImporter(); 
XmlTypeMapping mapping = importer.ImportTypeMapping(type); 
CompilerParameters parameters = new CompilerParameters(); 
Assembly xmlAssembly = XmlSerializer.GenerateSerializer(new Type[] { type }, new XmlMapping[] { mapping }, parameters); 

与我之前提出的解决方法一样,如果添加了第二种类型,该类型从程序集1中的类派生,则可以避免异常。

组装所需的另外两个类:

public class Test : BaseObject 
{ 
} 

生成序列化程序集更新逻辑:

Type type = typeof(TestClass); 
Assembly assembly = type.Assembly; 
XmlReflectionImporter importer = new XmlReflectionImporter(); 
XmlTypeMapping mapping = importer.ImportTypeMapping(type); 
Type type2 = typeof(Test); 
XmlReflectionImporter importer2 = new XmlReflectionImporter(); 
XmlTypeMapping mapping2 = importer2.ImportTypeMapping(type2); 
CompilerParameters parameters = new CompilerParameters(); 
Assembly xmlAssembly = XmlSerializer.GenerateSerializer(new Type[] { type, type2 }, new XmlMapping[] { mapping, mapping2 }, parameters); 
+1

不幸的是包含在Windows SDK的8.0A版本SGEN的版本似乎有解决了我遇到的问题,在升级之前我无法测试您的建议。感谢您的回应,'sgen'标签在这里很少受到关注。 – roken