Retrieve generic contract names for Managed Extensibility Framework











up vote
1
down vote

favorite












Edit
Found the original contract name resolution by .NET MEF, the code below is not useful anymore. See response!



My issue was to use existing code, to make a MEF ExportFactory, imported via [Import] attribute to a property, return instances of Moq mocks (for unit testing). Problem was, that the original code always used the Type.FullName property value as contract name. This worked fine for non-generic types, but not for generics.



Generic FullName is like:




My.Assembly.GenericType`1[My.Assembly.InnerType]



but MEF expects a name like:




My.Assembly.GenericType(My.Assembly.InnerType)



The complete unit test code actually extends the MEF ExportProvider class, to register ExportDefinition instances for an ExportFactory and it's ProductDefinition. The contract name goes to a metadata dictionary, using the key CompositionConstants.ExportTypeIdentityMetadataName.



This following code is only for the contract name conversion. It calls itself recursively, for generic arguments which are generic themselves. The regular expression matches by the `[digits] name extension, used by .NET for generic types. It would be nice to see a generally better way, or already existing functions from MEF, if such exists.



Edit: I added the incrementor and code for open (unspecified) generics, which have names with indexed curly brackets: instead of IMyType<string,int> IMyType<,>, resolved to contract name IMyType({0},{1}). Regex has also been changed to match, if no type names come after `[digits].



private static readonly Regex GenericRegex = 
new Regex(@"^(?<fullNameNonGeneric>S+?)`d+([.*])*$",
RegexOptions.Compiled);


public static string ResolveGenericMefContractName(this Type type)
{
return ResolveGenericMefContractName(type, new IndexIncrementor());
}

private static string ResolveGenericMefContractName(Type type, IndexIncrementor incrementor)
{
var fullName = type?.FullName;
if (fullName == null)
{
return null;
}
var match = GenericRegex.Match(fullName);
if (!match.Success)
{
return type.FullName;
}

var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;
var genericArgs = type.GetGenericArguments();

return fullNameNonGeneric + "(" +
string.Join(",", genericArgs.Select(
ga => ResolveGenericMefContractName(ga, incrementor)
?? "{" + incrementor.GetAndIncrementValue() + "}"))
+ ")";
}

private class IndexIncrementor
{
private int _value;

public int GetAndIncrementValue() => _value++;
}









share|improve this question




























    up vote
    1
    down vote

    favorite












    Edit
    Found the original contract name resolution by .NET MEF, the code below is not useful anymore. See response!



    My issue was to use existing code, to make a MEF ExportFactory, imported via [Import] attribute to a property, return instances of Moq mocks (for unit testing). Problem was, that the original code always used the Type.FullName property value as contract name. This worked fine for non-generic types, but not for generics.



    Generic FullName is like:




    My.Assembly.GenericType`1[My.Assembly.InnerType]



    but MEF expects a name like:




    My.Assembly.GenericType(My.Assembly.InnerType)



    The complete unit test code actually extends the MEF ExportProvider class, to register ExportDefinition instances for an ExportFactory and it's ProductDefinition. The contract name goes to a metadata dictionary, using the key CompositionConstants.ExportTypeIdentityMetadataName.



    This following code is only for the contract name conversion. It calls itself recursively, for generic arguments which are generic themselves. The regular expression matches by the `[digits] name extension, used by .NET for generic types. It would be nice to see a generally better way, or already existing functions from MEF, if such exists.



    Edit: I added the incrementor and code for open (unspecified) generics, which have names with indexed curly brackets: instead of IMyType<string,int> IMyType<,>, resolved to contract name IMyType({0},{1}). Regex has also been changed to match, if no type names come after `[digits].



    private static readonly Regex GenericRegex = 
    new Regex(@"^(?<fullNameNonGeneric>S+?)`d+([.*])*$",
    RegexOptions.Compiled);


    public static string ResolveGenericMefContractName(this Type type)
    {
    return ResolveGenericMefContractName(type, new IndexIncrementor());
    }

    private static string ResolveGenericMefContractName(Type type, IndexIncrementor incrementor)
    {
    var fullName = type?.FullName;
    if (fullName == null)
    {
    return null;
    }
    var match = GenericRegex.Match(fullName);
    if (!match.Success)
    {
    return type.FullName;
    }

    var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;
    var genericArgs = type.GetGenericArguments();

    return fullNameNonGeneric + "(" +
    string.Join(",", genericArgs.Select(
    ga => ResolveGenericMefContractName(ga, incrementor)
    ?? "{" + incrementor.GetAndIncrementValue() + "}"))
    + ")";
    }

    private class IndexIncrementor
    {
    private int _value;

    public int GetAndIncrementValue() => _value++;
    }









    share|improve this question


























      up vote
      1
      down vote

      favorite









      up vote
      1
      down vote

      favorite











      Edit
      Found the original contract name resolution by .NET MEF, the code below is not useful anymore. See response!



      My issue was to use existing code, to make a MEF ExportFactory, imported via [Import] attribute to a property, return instances of Moq mocks (for unit testing). Problem was, that the original code always used the Type.FullName property value as contract name. This worked fine for non-generic types, but not for generics.



      Generic FullName is like:




      My.Assembly.GenericType`1[My.Assembly.InnerType]



      but MEF expects a name like:




      My.Assembly.GenericType(My.Assembly.InnerType)



      The complete unit test code actually extends the MEF ExportProvider class, to register ExportDefinition instances for an ExportFactory and it's ProductDefinition. The contract name goes to a metadata dictionary, using the key CompositionConstants.ExportTypeIdentityMetadataName.



      This following code is only for the contract name conversion. It calls itself recursively, for generic arguments which are generic themselves. The regular expression matches by the `[digits] name extension, used by .NET for generic types. It would be nice to see a generally better way, or already existing functions from MEF, if such exists.



      Edit: I added the incrementor and code for open (unspecified) generics, which have names with indexed curly brackets: instead of IMyType<string,int> IMyType<,>, resolved to contract name IMyType({0},{1}). Regex has also been changed to match, if no type names come after `[digits].



      private static readonly Regex GenericRegex = 
      new Regex(@"^(?<fullNameNonGeneric>S+?)`d+([.*])*$",
      RegexOptions.Compiled);


      public static string ResolveGenericMefContractName(this Type type)
      {
      return ResolveGenericMefContractName(type, new IndexIncrementor());
      }

      private static string ResolveGenericMefContractName(Type type, IndexIncrementor incrementor)
      {
      var fullName = type?.FullName;
      if (fullName == null)
      {
      return null;
      }
      var match = GenericRegex.Match(fullName);
      if (!match.Success)
      {
      return type.FullName;
      }

      var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;
      var genericArgs = type.GetGenericArguments();

      return fullNameNonGeneric + "(" +
      string.Join(",", genericArgs.Select(
      ga => ResolveGenericMefContractName(ga, incrementor)
      ?? "{" + incrementor.GetAndIncrementValue() + "}"))
      + ")";
      }

      private class IndexIncrementor
      {
      private int _value;

      public int GetAndIncrementValue() => _value++;
      }









      share|improve this question















      Edit
      Found the original contract name resolution by .NET MEF, the code below is not useful anymore. See response!



      My issue was to use existing code, to make a MEF ExportFactory, imported via [Import] attribute to a property, return instances of Moq mocks (for unit testing). Problem was, that the original code always used the Type.FullName property value as contract name. This worked fine for non-generic types, but not for generics.



      Generic FullName is like:




      My.Assembly.GenericType`1[My.Assembly.InnerType]



      but MEF expects a name like:




      My.Assembly.GenericType(My.Assembly.InnerType)



      The complete unit test code actually extends the MEF ExportProvider class, to register ExportDefinition instances for an ExportFactory and it's ProductDefinition. The contract name goes to a metadata dictionary, using the key CompositionConstants.ExportTypeIdentityMetadataName.



      This following code is only for the contract name conversion. It calls itself recursively, for generic arguments which are generic themselves. The regular expression matches by the `[digits] name extension, used by .NET for generic types. It would be nice to see a generally better way, or already existing functions from MEF, if such exists.



      Edit: I added the incrementor and code for open (unspecified) generics, which have names with indexed curly brackets: instead of IMyType<string,int> IMyType<,>, resolved to contract name IMyType({0},{1}). Regex has also been changed to match, if no type names come after `[digits].



      private static readonly Regex GenericRegex = 
      new Regex(@"^(?<fullNameNonGeneric>S+?)`d+([.*])*$",
      RegexOptions.Compiled);


      public static string ResolveGenericMefContractName(this Type type)
      {
      return ResolveGenericMefContractName(type, new IndexIncrementor());
      }

      private static string ResolveGenericMefContractName(Type type, IndexIncrementor incrementor)
      {
      var fullName = type?.FullName;
      if (fullName == null)
      {
      return null;
      }
      var match = GenericRegex.Match(fullName);
      if (!match.Success)
      {
      return type.FullName;
      }

      var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;
      var genericArgs = type.GetGenericArguments();

      return fullNameNonGeneric + "(" +
      string.Join(",", genericArgs.Select(
      ga => ResolveGenericMefContractName(ga, incrementor)
      ?? "{" + incrementor.GetAndIncrementValue() + "}"))
      + ")";
      }

      private class IndexIncrementor
      {
      private int _value;

      public int GetAndIncrementValue() => _value++;
      }






      c# .net mef






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Dec 3 at 13:50

























      asked Nov 27 at 17:29









      Erik Hart

      202129




      202129






















          2 Answers
          2






          active

          oldest

          votes

















          up vote
          0
          down vote













          I see you've found the right solution but let's make a review anyway as there are few things that I'm not particularly fond of.






          var fullName = type?.FullName;
          if (fullName == null)
          {
          return null;
          }



          Instead of allowing type to be null, you should throw the ArgumentNullException. I cannot imagine any use-case where type being null would make sense. Usually this would mean a bug. You could return null later when resolving it fails but arguments should be always valid. Otherwise there are too many possibilities for the null result and it's could be difficult to tell why it didn't work.





          The method name is confusing becaues it says Resolve while it actually creates a MefContractName thus at first I thougt that when the regex fails here




          if (!match.Success)
          {
          return type.FullName;
          }



          then it should return null. While in the first casae this would make sense, it wouldn't for creation so I suggest naming this extension as ToMefContractName. Now it all makes sense again.



          I'm now sure what you need this IndexIncrementor for as the type should never be null so it will never be called.




          var genericArgs = type.GetGenericArguments();

          return fullNameNonGeneric + "(" +
          string.Join(",", genericArgs.Select(
          ga => ToMefContractName(ga, incrementor)
          ?? "{" + incrementor.Next() + "}"))
          + ")";



          You can turn this into a more readable query without the helper variable genericArgs that this time doesn't help in any way.



          This is how I think it should look like (with IndexIncrementor removed because I could figure out what it is for):



          private static string ToMefContractName(Type type)
          {
          if (type == null) throw new ArgumentNullException(nameof(type));

          var match = GenericRegex.Match(type.FullName);
          if (!match.Success)
          {
          return type.FullName;
          }

          var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;

          var genericArguments =
          from genericArgument in type.GetGenericArguments()
          select ToMefContractName(genericArgument);

          return $"{fullNameNonGeneric}({string.Join(",", genericArguments)})";
          }




          The IndexIncrementor should be called just Index and have one read-only property named Value and its method should be called Next. Saying GetAndIncrementValue reveals the internal implementation and this is not important to the user, he just wants to have the next value.



          private class Index
          {
          public int Value { get; private set; }

          public int Next() => Value++;
          }





          share|improve this answer





















          • OK, thanks. But on Type, method GetGenericArguments() returns null for open generics; in this case, the code worked as desired. This is different from the GenericTypeArguments property, which returns only specified generic arguments. I just noticed this later, when trying again with the property.
            – Erik Hart
            16 hours ago


















          up vote
          -1
          down vote



          accepted










          The code in the question was an attempt to generate type contract names, from the way I saw how MEF created them. Especially the difference from Type.FullName, which was previously used, when getting a contract name. For this reason, the code is a probably inferior re-implementation of MEF's own name generation, and should not be used for this purpose.



          This is the contract name resolution used by MEF in .NET framework (maybe different namespace in Core, Apps etc.):



          Namespace:




          System.ComponentModel.Composition



          Static method:




          AttributedModelServices.GetContractName(Type)



          Unfortunately, it's often easier to re-invent the wheel, than to find out about existing implementations...






          share|improve this answer













          We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.














          • Now I know what you mean - thanks for adding the explanation ;-)
            – t3chb0t
            19 hours ago











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208550%2fretrieve-generic-contract-names-for-managed-extensibility-framework%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          0
          down vote













          I see you've found the right solution but let's make a review anyway as there are few things that I'm not particularly fond of.






          var fullName = type?.FullName;
          if (fullName == null)
          {
          return null;
          }



          Instead of allowing type to be null, you should throw the ArgumentNullException. I cannot imagine any use-case where type being null would make sense. Usually this would mean a bug. You could return null later when resolving it fails but arguments should be always valid. Otherwise there are too many possibilities for the null result and it's could be difficult to tell why it didn't work.





          The method name is confusing becaues it says Resolve while it actually creates a MefContractName thus at first I thougt that when the regex fails here




          if (!match.Success)
          {
          return type.FullName;
          }



          then it should return null. While in the first casae this would make sense, it wouldn't for creation so I suggest naming this extension as ToMefContractName. Now it all makes sense again.



          I'm now sure what you need this IndexIncrementor for as the type should never be null so it will never be called.




          var genericArgs = type.GetGenericArguments();

          return fullNameNonGeneric + "(" +
          string.Join(",", genericArgs.Select(
          ga => ToMefContractName(ga, incrementor)
          ?? "{" + incrementor.Next() + "}"))
          + ")";



          You can turn this into a more readable query without the helper variable genericArgs that this time doesn't help in any way.



          This is how I think it should look like (with IndexIncrementor removed because I could figure out what it is for):



          private static string ToMefContractName(Type type)
          {
          if (type == null) throw new ArgumentNullException(nameof(type));

          var match = GenericRegex.Match(type.FullName);
          if (!match.Success)
          {
          return type.FullName;
          }

          var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;

          var genericArguments =
          from genericArgument in type.GetGenericArguments()
          select ToMefContractName(genericArgument);

          return $"{fullNameNonGeneric}({string.Join(",", genericArguments)})";
          }




          The IndexIncrementor should be called just Index and have one read-only property named Value and its method should be called Next. Saying GetAndIncrementValue reveals the internal implementation and this is not important to the user, he just wants to have the next value.



          private class Index
          {
          public int Value { get; private set; }

          public int Next() => Value++;
          }





          share|improve this answer





















          • OK, thanks. But on Type, method GetGenericArguments() returns null for open generics; in this case, the code worked as desired. This is different from the GenericTypeArguments property, which returns only specified generic arguments. I just noticed this later, when trying again with the property.
            – Erik Hart
            16 hours ago















          up vote
          0
          down vote













          I see you've found the right solution but let's make a review anyway as there are few things that I'm not particularly fond of.






          var fullName = type?.FullName;
          if (fullName == null)
          {
          return null;
          }



          Instead of allowing type to be null, you should throw the ArgumentNullException. I cannot imagine any use-case where type being null would make sense. Usually this would mean a bug. You could return null later when resolving it fails but arguments should be always valid. Otherwise there are too many possibilities for the null result and it's could be difficult to tell why it didn't work.





          The method name is confusing becaues it says Resolve while it actually creates a MefContractName thus at first I thougt that when the regex fails here




          if (!match.Success)
          {
          return type.FullName;
          }



          then it should return null. While in the first casae this would make sense, it wouldn't for creation so I suggest naming this extension as ToMefContractName. Now it all makes sense again.



          I'm now sure what you need this IndexIncrementor for as the type should never be null so it will never be called.




          var genericArgs = type.GetGenericArguments();

          return fullNameNonGeneric + "(" +
          string.Join(",", genericArgs.Select(
          ga => ToMefContractName(ga, incrementor)
          ?? "{" + incrementor.Next() + "}"))
          + ")";



          You can turn this into a more readable query without the helper variable genericArgs that this time doesn't help in any way.



          This is how I think it should look like (with IndexIncrementor removed because I could figure out what it is for):



          private static string ToMefContractName(Type type)
          {
          if (type == null) throw new ArgumentNullException(nameof(type));

          var match = GenericRegex.Match(type.FullName);
          if (!match.Success)
          {
          return type.FullName;
          }

          var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;

          var genericArguments =
          from genericArgument in type.GetGenericArguments()
          select ToMefContractName(genericArgument);

          return $"{fullNameNonGeneric}({string.Join(",", genericArguments)})";
          }




          The IndexIncrementor should be called just Index and have one read-only property named Value and its method should be called Next. Saying GetAndIncrementValue reveals the internal implementation and this is not important to the user, he just wants to have the next value.



          private class Index
          {
          public int Value { get; private set; }

          public int Next() => Value++;
          }





          share|improve this answer





















          • OK, thanks. But on Type, method GetGenericArguments() returns null for open generics; in this case, the code worked as desired. This is different from the GenericTypeArguments property, which returns only specified generic arguments. I just noticed this later, when trying again with the property.
            – Erik Hart
            16 hours ago













          up vote
          0
          down vote










          up vote
          0
          down vote









          I see you've found the right solution but let's make a review anyway as there are few things that I'm not particularly fond of.






          var fullName = type?.FullName;
          if (fullName == null)
          {
          return null;
          }



          Instead of allowing type to be null, you should throw the ArgumentNullException. I cannot imagine any use-case where type being null would make sense. Usually this would mean a bug. You could return null later when resolving it fails but arguments should be always valid. Otherwise there are too many possibilities for the null result and it's could be difficult to tell why it didn't work.





          The method name is confusing becaues it says Resolve while it actually creates a MefContractName thus at first I thougt that when the regex fails here




          if (!match.Success)
          {
          return type.FullName;
          }



          then it should return null. While in the first casae this would make sense, it wouldn't for creation so I suggest naming this extension as ToMefContractName. Now it all makes sense again.



          I'm now sure what you need this IndexIncrementor for as the type should never be null so it will never be called.




          var genericArgs = type.GetGenericArguments();

          return fullNameNonGeneric + "(" +
          string.Join(",", genericArgs.Select(
          ga => ToMefContractName(ga, incrementor)
          ?? "{" + incrementor.Next() + "}"))
          + ")";



          You can turn this into a more readable query without the helper variable genericArgs that this time doesn't help in any way.



          This is how I think it should look like (with IndexIncrementor removed because I could figure out what it is for):



          private static string ToMefContractName(Type type)
          {
          if (type == null) throw new ArgumentNullException(nameof(type));

          var match = GenericRegex.Match(type.FullName);
          if (!match.Success)
          {
          return type.FullName;
          }

          var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;

          var genericArguments =
          from genericArgument in type.GetGenericArguments()
          select ToMefContractName(genericArgument);

          return $"{fullNameNonGeneric}({string.Join(",", genericArguments)})";
          }




          The IndexIncrementor should be called just Index and have one read-only property named Value and its method should be called Next. Saying GetAndIncrementValue reveals the internal implementation and this is not important to the user, he just wants to have the next value.



          private class Index
          {
          public int Value { get; private set; }

          public int Next() => Value++;
          }





          share|improve this answer












          I see you've found the right solution but let's make a review anyway as there are few things that I'm not particularly fond of.






          var fullName = type?.FullName;
          if (fullName == null)
          {
          return null;
          }



          Instead of allowing type to be null, you should throw the ArgumentNullException. I cannot imagine any use-case where type being null would make sense. Usually this would mean a bug. You could return null later when resolving it fails but arguments should be always valid. Otherwise there are too many possibilities for the null result and it's could be difficult to tell why it didn't work.





          The method name is confusing becaues it says Resolve while it actually creates a MefContractName thus at first I thougt that when the regex fails here




          if (!match.Success)
          {
          return type.FullName;
          }



          then it should return null. While in the first casae this would make sense, it wouldn't for creation so I suggest naming this extension as ToMefContractName. Now it all makes sense again.



          I'm now sure what you need this IndexIncrementor for as the type should never be null so it will never be called.




          var genericArgs = type.GetGenericArguments();

          return fullNameNonGeneric + "(" +
          string.Join(",", genericArgs.Select(
          ga => ToMefContractName(ga, incrementor)
          ?? "{" + incrementor.Next() + "}"))
          + ")";



          You can turn this into a more readable query without the helper variable genericArgs that this time doesn't help in any way.



          This is how I think it should look like (with IndexIncrementor removed because I could figure out what it is for):



          private static string ToMefContractName(Type type)
          {
          if (type == null) throw new ArgumentNullException(nameof(type));

          var match = GenericRegex.Match(type.FullName);
          if (!match.Success)
          {
          return type.FullName;
          }

          var fullNameNonGeneric = match.Groups["fullNameNonGeneric"].Value;

          var genericArguments =
          from genericArgument in type.GetGenericArguments()
          select ToMefContractName(genericArgument);

          return $"{fullNameNonGeneric}({string.Join(",", genericArguments)})";
          }




          The IndexIncrementor should be called just Index and have one read-only property named Value and its method should be called Next. Saying GetAndIncrementValue reveals the internal implementation and this is not important to the user, he just wants to have the next value.



          private class Index
          {
          public int Value { get; private set; }

          public int Next() => Value++;
          }






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 18 hours ago









          t3chb0t

          33.7k746110




          33.7k746110












          • OK, thanks. But on Type, method GetGenericArguments() returns null for open generics; in this case, the code worked as desired. This is different from the GenericTypeArguments property, which returns only specified generic arguments. I just noticed this later, when trying again with the property.
            – Erik Hart
            16 hours ago


















          • OK, thanks. But on Type, method GetGenericArguments() returns null for open generics; in this case, the code worked as desired. This is different from the GenericTypeArguments property, which returns only specified generic arguments. I just noticed this later, when trying again with the property.
            – Erik Hart
            16 hours ago
















          OK, thanks. But on Type, method GetGenericArguments() returns null for open generics; in this case, the code worked as desired. This is different from the GenericTypeArguments property, which returns only specified generic arguments. I just noticed this later, when trying again with the property.
          – Erik Hart
          16 hours ago




          OK, thanks. But on Type, method GetGenericArguments() returns null for open generics; in this case, the code worked as desired. This is different from the GenericTypeArguments property, which returns only specified generic arguments. I just noticed this later, when trying again with the property.
          – Erik Hart
          16 hours ago












          up vote
          -1
          down vote



          accepted










          The code in the question was an attempt to generate type contract names, from the way I saw how MEF created them. Especially the difference from Type.FullName, which was previously used, when getting a contract name. For this reason, the code is a probably inferior re-implementation of MEF's own name generation, and should not be used for this purpose.



          This is the contract name resolution used by MEF in .NET framework (maybe different namespace in Core, Apps etc.):



          Namespace:




          System.ComponentModel.Composition



          Static method:




          AttributedModelServices.GetContractName(Type)



          Unfortunately, it's often easier to re-invent the wheel, than to find out about existing implementations...






          share|improve this answer













          We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.














          • Now I know what you mean - thanks for adding the explanation ;-)
            – t3chb0t
            19 hours ago















          up vote
          -1
          down vote



          accepted










          The code in the question was an attempt to generate type contract names, from the way I saw how MEF created them. Especially the difference from Type.FullName, which was previously used, when getting a contract name. For this reason, the code is a probably inferior re-implementation of MEF's own name generation, and should not be used for this purpose.



          This is the contract name resolution used by MEF in .NET framework (maybe different namespace in Core, Apps etc.):



          Namespace:




          System.ComponentModel.Composition



          Static method:




          AttributedModelServices.GetContractName(Type)



          Unfortunately, it's often easier to re-invent the wheel, than to find out about existing implementations...






          share|improve this answer













          We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.














          • Now I know what you mean - thanks for adding the explanation ;-)
            – t3chb0t
            19 hours ago













          up vote
          -1
          down vote



          accepted







          up vote
          -1
          down vote



          accepted






          The code in the question was an attempt to generate type contract names, from the way I saw how MEF created them. Especially the difference from Type.FullName, which was previously used, when getting a contract name. For this reason, the code is a probably inferior re-implementation of MEF's own name generation, and should not be used for this purpose.



          This is the contract name resolution used by MEF in .NET framework (maybe different namespace in Core, Apps etc.):



          Namespace:




          System.ComponentModel.Composition



          Static method:




          AttributedModelServices.GetContractName(Type)



          Unfortunately, it's often easier to re-invent the wheel, than to find out about existing implementations...






          share|improve this answer














          The code in the question was an attempt to generate type contract names, from the way I saw how MEF created them. Especially the difference from Type.FullName, which was previously used, when getting a contract name. For this reason, the code is a probably inferior re-implementation of MEF's own name generation, and should not be used for this purpose.



          This is the contract name resolution used by MEF in .NET framework (maybe different namespace in Core, Apps etc.):



          Namespace:




          System.ComponentModel.Composition



          Static method:




          AttributedModelServices.GetContractName(Type)



          Unfortunately, it's often easier to re-invent the wheel, than to find out about existing implementations...







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited 19 hours ago









          t3chb0t

          33.7k746110




          33.7k746110










          answered Dec 3 at 13:54









          Erik Hart

          202129




          202129



          We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.




          We're looking for long answers that provide some explanation and context. Don't just give a one-line answer; explain why your answer is right, ideally with citations. Answers that don't include explanations may be removed.













          • Now I know what you mean - thanks for adding the explanation ;-)
            – t3chb0t
            19 hours ago


















          • Now I know what you mean - thanks for adding the explanation ;-)
            – t3chb0t
            19 hours ago
















          Now I know what you mean - thanks for adding the explanation ;-)
          – t3chb0t
          19 hours ago




          Now I know what you mean - thanks for adding the explanation ;-)
          – t3chb0t
          19 hours ago


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f208550%2fretrieve-generic-contract-names-for-managed-extensibility-framework%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Terni

          A new problem with tex4ht and tikz

          Sun Ra