1

First of all I know that the title is not so good but the thing is I dont even know how to explain my question; I'll just show an example below on what I'm trying to do:

EDIT: I should have given a better example to begin with; let's try again:

// MyAppComponentModel.dll
namespace MyAppComponentModel {
  using System.Collections;

  interface IResource { }
  interface IStringResource : IResource { }
  interface IIconResource : IResource { }
  interface IDialogResource : IResource { }
  interface IResourceProvider {
    void GetResource<T>(out T result, IDictionary criteria = null) where T : IResource;
  }
}

// ThirdPartyLib.dll
namespace ResourceProviderLibA {
  using System.Collections;
  using System.ComponentModel.Composition;
  using MyAppComponentModel.

  public sealed class StringResource : IStringResource { ... }
  public sealed class IconResource : IIconResource { ... }

  [Export(typeof(IResourceProvider))]
  public sealed class StringAndIconResourceProvider : IResourceProvider {
    void IResourceProvider.Get<T>(out T result, IDictionary criteria) {
      if (typeof(T) == typeof(IDialogResource))
        throw new NotSupportedException();

      this.InternalGet(out result, criteria);
    }

    void InternalGet(out IStringResource result, IDictionary criteria) {
      result = new StringResource();
      ...
    }

    void InternalGet(out IIconResource result, IDictionary criteria) {
      result = new IconResource();
      ...
    }
  }
}

// MyMefTestApp.exe
namespace MyMefTestApp {
  using System.Collections.Generic;
  using System.ComponentModel.Composition.Hosting;
  using MyAppComponentModel.

  static class Program {
    [ImportMany(typeof(IResourceProvider))]
    private IEnumerable<IResourceProvider> mProviders;

    static void Main(String[] args) {
      foreach (var provider in this.mProviders) {
        ...
      }
    }
  }
}

I know it's somehow possible and I strongly believe I did something like this once just dont remember how. Anyone?

I already know that this can be done via Reflection so please skip those solutions - thanks.

2 Answers 2

2

This is not possible as T can be anything (the compiler error actually is cannot convert from 'out T' to 'out string'), not just a string or int.

Just expose the privateFoo overloads as public Foo and be done with it, there is no other way as you can't restrict a generic to string or int (both are sealed, and a generic type constraint needs an interface or non sealed class).

edit (changed question)

If your Resource implementation only have parameterless constructors, I would use this (condensed example):

interface IHostProvider
{
  void Get<T> (out T result) where T : IHost,  new();
}

public interface IHost
{
}

public class Something : IHost
{
}

public class Provider : IHostProvider
{
  public void Get<T> (out T result) where T: IHost, new()
    {
      result = new T();
    }
}

If they require parameters however... phew, no idea this late at night. At first I had a static factory method in mind, but as you can't require a static method in an interface nor mark it abstract, this won't work either.

Sign up to request clarification or add additional context in comments.

1 Comment

I've updated the example code to a more practical example; please take a look at it and see if it changes your answer in any way. I really need some help here or at least a "good programming" way to solve this problem.
0

Your sample seems to me impossible. Compiler can infer type arguments of method from known actual parameter types. For example:

void DoSomething<T>(T item)
{
    ...
}

IFoo foo =  default(IFoo);
DoSomething(foo); // void DoSomething<IFoo>(IFoo item);

But compiler can't do opposite. Compiler can't guess T's actual type and that's why it can't select applicable method overload.

void DoSomething(IFoo foo)
{
    ...
}

T item = default(T);
DoSomething(item); // won't compile unless it is known that T is IFoo (where T : IFoo)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.