我刚为Jon Skeet的Unconstrained Melody项目安装了nuget包,但是当我尝试使用它时,编译时出错:
类型参数'T'继承冲突约束'UnconstrainedMelody.IEnumConstraint'和'System.ValueType'
功能定义:
public void SetEnum<T>() where T : struct, IEnumConstraint {}
我错过了什么吗?我不应该使用nuget包吗?
答案 0 :(得分:2)
我可能是错的,但看起来虽然这个库在内部使用IEnumConstraint
,并且让它与本文中描述的后构建步骤一起使用,但不提供任何魔法让你直接使用IEnumConstraint
为自己的方法。
帖子中描述的GetValues<T>
方法是UnconstrainedMelody.Enums
类提供的几种方法之一。还有其他对象和方法。
如果您想将自己的通用方法约束为枚举,可以按照Jon用于构建此库的相同步骤,但在您自己的库上。在如何使用PostSharp执行此操作的评论中也有this example。
答案 1 :(得分:2)
&#34;无拘无束的旋律&#34;已经整合到
它带有必要的工具,可以将IL编织结合到构建过程中并且正在积极维护。因此,对于来自&#34;无约束旋律&#34;的代码,最好使用它。对于枚举,Enums.NET还提供了其他改进。
ExtraConstraints还支持向委托添加约束。
答案 2 :(得分:0)
我还没试过这个,但似乎你可以使用这个MSBuild任务来完成与ConstraintChanger相同的事情。您必须在项目中包含DelegateConstraint.cs和IEnumConstraint.cs代码文件的副本。将构建任务应用于项目后,将交换约束,并且引用此项目的其他项目将能够查看约束。
因此,它对于在您的解决方案中创建公共库项目非常有用,并且可以包含类似于System.Enum和System.Delegate类型的自定义通用扩展方法。
https://code.google.com/p/unconstrained-melody/issues/detail?id=13
所有信用:j ... @ friesen.us
I've found this project to be useful but wanted to have the build-time steps in MSBuild. Adding this to your *.csproj files in which you use the constraints should accomplish the same thing as the Constraintchanger app. Note the following:
1. I've added the two constraint types to my classes root namespace and the substitution looks for the types in the assembly's root namespace.
2. To make Resharper happier I've added the IEnumConstraint, DelegateConstraint type args into my project inside an #if UNCONSTRAINED ... #endif block like so:
public static T Parse<T>(string val) where T : struct
#if UNCONSTRAINED
, IEnumConstraint
#endif
{
}
This is purely optional but keeps resharper from complaining about the constraint not matching when using the project's code from another project in a common solution.
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
SwapConstraints
</BuildDependsOn>
</PropertyGroup>
<ItemGroup>
<PreprocessorDefines Include="UNCONSTRAINED" />
</ItemGroup>
<UsingTask TaskName="FileReplace" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<FileName ParameterType="System.String" Required="true" />
<Source ParameterType="System.String" Required="true" />
<Replacement ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs"><![CDATA[
string content = File.ReadAllText(FileName);
content = content.Replace(Source, Replacement);
File.WriteAllText(FileName, content);
]]></Code>
</Task>
</UsingTask>
<Target Name="SwapConstraints">
<GetFrameworkPath>
<Output TaskParameter="Path" PropertyName="FW" />
</GetFrameworkPath>
<GetFrameworkSdkPath>
<Output TaskParameter="Path" PropertyName="SDK" />
</GetFrameworkSdkPath>
<PropertyGroup>
<ILDASM>"$(SDK)bin\NETFX 4.0 Tools\ildasm.exe"</ILDASM>
<ILASM>"$(FW)\ilasm.exe"</ILASM>
<IlFile>$(OutputPath)$(AssemblyName).il</IlFile>
<DllFile>$(OutputPath)$(AssemblyName).dll</DllFile>
</PropertyGroup>
<Exec Command="$(ILDASM) /OUT=$(IlFile) $(DllFile)" WorkingDirectory="$(ProjectDir)" />
<FileReplace FileName="$(IlFile)" Source="($(RootNamespace).DelegateConstraint)" Replacement="([mscorlib]System.Delegate)" />
<FileReplace FileName="$(IlFile)" Source="([mscorlib]System.ValueType, $(RootNamespace).IEnumConstraint)" Replacement="([mscorlib]System.Enum)" />
<FileReplace FileName="$(IlFile)" Source="($(RootNamespace).IEnumConstraint), [mscorlib]System.ValueType" Replacement="([mscorlib]System.Enum)" />
<FileReplace FileName="$(IlFile)" Source="($(RootNamespace).IEnumConstraint)" Replacement="([mscorlib]System.Enum)" />
<Exec Command="$(ILASM) /OUTPUT=$(DllFile) /DLL $(IlFile)" WorkingDirectory="$(ProjectDir)" />
</Target>
Nov 22, 2013
#1 j...@friesen.us
Sorry, didn't mean to say #if UNCONSTRAINED ... #endif should be around type args for DelegateConstraint. I've not messed with delegates to this point but I doubt that it would be necessary for them.