0

我有一个接口的具体类实现,它有一个像这样的方法声明......

public interface IControllerContent
{
     IEnumerable<KeyValuePair<string, string>> LocalResource();
}

public class BaseControllerContent : IControllerContent
{

   public IEnumerable<KeyValuePair<string, string>> LocalResource()
   {
     ResourceSet resourceSet =
     ResourceManager.GetResourceSet(new CultureInfo(this.Tenant.Locale), true, false);

     IDictionaryEnumerator dictionaryEnumerator = resourceSet.GetEnumerator();

        while (dictionaryEnumerator.MoveNext())
        {
            //only string resources
            var value = dictionaryEnumerator.Value as string;
            if (value != null)
            {
                var key = (string)dictionaryEnumerator.Key;
                yield return new KeyValuePair<string, string>(key, value);
            }
        }
    }
}

一切都相当直截了当。声明一个接口并从一个具体类实现。但是,当我尝试调用具体类的 LocalResource 方法时,我得到了一个异常。

public T Build<T>() where T : class, IControllerContent
{
     var controllerContent = Activator.CreateInstance(typeof(T)) as T;
     try
     {
         **controllerContent.CDict = (Dictionary<string, string>) controllerContent.LocalResource();**
         controllerContent.CDict = (Dictionary<string, string>) JsonReader<T>.Parse(this.Content);
         return controllerContent;
      }
      catch (Exception ex)
      {
         throw new Exception();
      }
}

尝试执行 LocalResource() 方法(上面突出显示)时发生异常。

{System.InvalidCastException:无法将“<LocalResource>d__0”类型的对象转换为“System.Collections.Generic.Dictionary`2[System.String,System.String]”类型。在 FantasyLeague.Web.Mvc.ControllerContentBuilder.BuildT 在 C:\Users\andrew.knightley\git\FAST\src\ContentManagement\FantasyLeague.Web.Mvc\ControllerBase.cs:line 290}

基本上,C# 似乎试图将接口方法签名解析为字典,因此出现错误,但它肯定应该尝试执行具体的实现。有人知道这里发生了什么吗?我尝试过转换为接口和具体类型以及所有组合,但它仍然没有。我已经重读了关于接口的所有 MSDN 资料,根据他们的文章,这里没有什么不寻常的地方。

提前谢谢了。

4

2 回答 2

3

简而言之,您的实现没有返回 a Dictionary<string, string>,因此您不能对其进行强制转换。您只是返回一系列键/值对 - 这与字典不同。

请注意,这与在接口上声明的方法无关 - 您正在调用正确的实现,而只是转换结果。您可以通过将两者分开来看到这一点:

IEnumerable<KeyValuePair<string, string>> tmp = controllerContent.LocalResource();
controllerContent.CDict = (Dictionary<string, string>) tmp; // Bang!

最简单的解决方法是使用 LINQ 创建字典:

controllerContent.CDict = controllerContent.LocalResource()
                                           .ToDictionary(x => x.Key, x => x.Value);

请注意,您的LocalResource()方法的替代实现也可以使用 LINQ:

public IEnumerable<KeyValuePair<string, string>> LocalResource()
{
    ResourceSet resourceSet = ResourceManager.GetResourceSet(
        new CultureInfo(this.Tenant.Locale), true, false);
    return resourceSet.Cast<DictionaryEntry>()
                      .Where(de => de.Value is string)
                      .Select(de => new KeyValuePair((string) de.Key,
                                                     (string) de.Value));
}

这将最终装箱 each DictionaryEntry,但它比您的迭代器块方法 IMO 更简单。

于 2013-09-18T11:19:45.790 回答
0

问题在于您的方法结果的演员表->Dictionary<string,string>

在 LinqPad 中尝试以下代码以查看问题。

void Main()
{

    Dictionary<string, string> results  = (Dictionary<string, string>)GetResults();
}

public IEnumerable<KeyValuePair<string, string>> GetResults()
{
    yield return new KeyValuePair<string,string>("a", "a");
    yield return new KeyValuePair<string,string>("b", "b");
    yield return new KeyValuePair<string,string>("c", "c");
}

您不能直接从IEnumerable<KeyValuePair<string,string>>to投射Dictionary<string,string>

尝试将您的转换更改为以下

var x = GetResults();
Dictionary<string, string> results  = x.ToDictionary(y => y.Key, y => y.Value);
于 2013-09-18T11:23:30.450 回答