3

Jon Skeet の Unconstrained Melodyプロジェクトの nuget パッケージをインストールしましたが、使用しようとすると、コンパイル時にエラーが発生します。

型パラメーター 'T' は、競合する制約 'UnconstrainedMelody.IEnumConstraint' および 'System.ValueType' を継承します

関数定義:

public void SetEnum<T>() where T : struct, IEnumConstraint {}

何か不足していますか?nuget パッケージを使用しないでください。

4

3 に答える 3

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.
于 2015-02-12T02:03:04.700 に答える