【问题标题】:Instantiating using factory throwing exception使用工厂抛出异常进行实例化
【发布时间】:2015-06-11 14:29:23
【问题描述】:

首先我会说我是新手,所以我可能会犯一个非常简单的错误,但我只是没有看到它。我有以下工厂:

using System;
using System.Collections.Specialized;
using System.Configuration;

namespace SportsCardInventory.Services
{
    public class Factory
    {
        public IService GetService(string servicename)
        {
            Type type;
            Object obj = null;

            try
            {
                string ImplName = GetImplName(servicename);
                type = Type.GetType(ImplName);
                //obj = Activator.CreateInstance(type);
                obj = Activator.CreateInstance(typeof (ICreateCollection));
                return (IService)obj;
            }
            catch (Exception e)
            {
                Console.Write(e);
                throw;
            }
        }

        private string GetImplName(string servicename)
        {
            NameValueCollection settings = ConfigurationManager.AppSettings;
            return settings.Get(servicename);
        }
    }
}

还有如下界面:

using SportsCardInventory.Domain;

namespace SportsCardInventory.Services
{
    interface ICreateCollection:IService
    {
        bool CreateCollection(CardCollection newCollection);
    }
}

以及以下实现:

using System;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using SportsCardInventory.Domain;

namespace SportsCardInventory.Services
{
    class CreateCollectionImpl:ICreateCollection
    {
        public string CollectionName;
        public ArrayList CardCollection;
        public bool CreateCollection(CardCollection newCollection)
        {
            if (newCollection == null) throw new ArgumentNullException("newCollection");
            StoreCollection(newCollection);
            return true;
        }

        private void StoreCollection(CardCollection newCollection)
        {
            string fileName = newCollection.CollectionName + ".bin";
            FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
            IFormatter formatter = new BinaryFormatter();
            formatter.Serialize(fileStream, newCollection);
            fileStream.Close();
        }
    }
}

我正在尝试运行以下单元测试:

using System.Collections;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SportsCardInventory.Domain;
using SportsCardInventory.Services;

namespace ServicesTest
{
    [TestClass]
    public class CreateCollectionImplTest
    {
        [TestMethod]
        public void TestMethodCreateCollection()
        {
            bool testPassed;
            ArrayList testArrayList = new ArrayList();
            CardCollection testCollection = new CardCollection("TestCollection", testArrayList);
            Factory factory = new Factory();
            IService createCollectionService = (IService)factory.GetService("ICreateCollection");
        }
    }
}

我得到以下异常:

Test method ServicesTest.CreateCollectionImplTest.TestMethodCreateCollection threw exception: 

System.MissingMethodException: Cannot create an instance of an interface.
    at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, ref Boolean canBeCached, ref RuntimeMethodHandleInternal ctor, ref Boolean bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, ref StackCrawlMark stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, ref StackCrawlMark stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at SportsCardInventory.Services.Factory.GetService(String servicename) in Factory.cs: line 25
   at ServicesTest.CreateCollectionImplTest.TestMethodCreateCollection() in CreateCollectionImplTest.cs: line 18

System.MissingMethodException: Cannot create an instance of an interface.
   at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
   at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Activator.CreateInstance(Type type)
   at SportsCardInventory.Services.Factory.GetService(String servicename) in c:\Users\jfshinevar\Desktop\SCIRefactored\SportsCardInventory\SportsCardInventory\Services\Factory.cs:line 19

我不完全了解正在发生的事情,我觉得我在追逐各种可能性,而每一种可能性都会导致更多问题。有人可以帮我理解为什么我很难创建 CreateCollectionImpl 的实例,以便我可以对创建集合并将其写入磁盘的能力进行单元测试吗?提前谢谢你。

【问题讨论】:

  • 就像现在一样,您的代码正在尝试创建硬编码的ICreateCollection 接口并失败。您已经注释掉了试图找到具体类型的行
  • @PanagiotisKanavos 你是对的。我对其进行了硬编码,因为那是我在 app.config 文件中的内容。看起来我在 app.config 文件中放置了错误的项目。我需要用 CreateCollectionImpl 替换键 ICreateCollection,然后返回查找具体类型的注释行。

标签: c# service-factory


【解决方案1】:

你只是传递接口名称,你需要传递一个具体的类名来实例化它。

你调用它的方式,它会尝试单独实例化接口。

【讨论】:

  • 好的,这绝对解决了问题。现在我想我只需要更改 app.config 文件中的键来引用实现而不是接口。我停止使用 app.config 文件进行故障排除。我必须等待几分钟才能接受您的回答,但它奏效了。
猜你喜欢
  • 1970-01-01
  • 2021-11-07
  • 2012-09-12
  • 2021-07-18
  • 2013-02-17
  • 1970-01-01
  • 1970-01-01
  • 2016-08-13
  • 1970-01-01
相关资源
最近更新 更多