如何将接口类型转换为具体类型

本文关键字:类型 类型转换 接口 | 更新日期: 2023-09-27 18:09:01

我试图模拟ManagementObjectSearcher类并创建了IManagementInfo接口,那么我如何将接口转换为ManagementObjectSearcher类呢?

 ManagementObjectSearcher s = new ManagementObjectSearcher();
 IManagementInfo info = s as IManagementInfo;

创建一个空信息对象

ManagementObjectSearcher s = new ManagementObjectSearcher();
 IManagementInfo info =IManagementInfo(s);

这给了我运行时错误(不能类型转换)

如何将接口类型转换为具体类型

你不能那样做。您想这样做是为了编写单元测试吗?如果你试图模拟一个你无法控制的类,那么你必须把它包装在另一个类中。

public class MyManagementObjectSearcherWrapper : IManagementInfo
{
    public void TheMethodToMock()
    {
        var searcher = new ManagementObjectSearcher();        
        // The code you want to mock goes here
    }
}

你像这样运行你的代码:

public void YourCode(IManagementInfo info)
{
    info.TheMethodToMock();
}

那么YourCode()将接受您的包装器或模拟对象。您可以使用IManagementInfo接口创建mock。

看起来好像你试图包装一个第三方/系统对象,以帮助单元测试。

说你的起点是

public class Dependency {
    public string Foo() {
       return "foo";  // machine, system, time, something else, dependent result
    }
    public string Bar() {
       return "bar";
    }
}
public class MySimpleClass {
    public string MyFunc() {
         return new Dependency().Foo();
    }
}
[TestMethod]
public void TestSimple() {
    var client = new MySimpleClass();
    Assert.AreEqual("foo", client.MyFunc());
}

我们在调用中创建依赖,因为我们认为创建成本没有保持依赖的实例重要。这要视情况而定。我们也可以很容易地在actor中创建一个Dependency,并存储一个副本,以便每次调用。无论哪种方式,我们都无法控制输出,这使得单元测试变得混乱。

我们需要为它创建一个代理。

1。为需要的成员定义一个接口
最有可能的是,我们不需要使用包装的所有成员,所以只在接口中包含我们关心的那些成员。

public interface IDependencyProxy {
    string Foo();
}

2。创建代理类
然后,我们创建一个代理类,包装依赖项和实现接口。同样,我们可以在开始时或在逐个调用的基础上创建。

public class DependencyProxy : IDependencyProxy {
    public string Foo() {
        return new Dependency.Foo();
    }
}

3。根据接口
定义客户端代码我们稍微修改了客户端代码,以使用IDependencyProxy接口而不是Dependency。有几种方法可以做到这一点。我通常使用内部变量,它从公共变量中获取依赖链。(使用[InternalsVisibleTo]允许单元测试看到它)

public class MyRevisedClass {
    private readonly IDependencyProxy dependency;
    public MyRevisedClass() 
       : this( new DependencyProxy()) {}
    internal MyRevisedClass(IDependencyProxy dependency) {
        this.dependency = dependency;
    }
    public string MyFunc() {
        return dependency.Foo();
    }
}

这允许我们为生产代码设置默认行为(调用System对象),并允许我们模拟出单元测试的结果。

[TestMethod]
public void TestRevisedDefault() {
     var client = new MyRevisedClass();
     Assert.AreEqual("foo", client.MyFunc());
}

[TestMethod]
public void TestRevisedWithMockedDependency() {
    var dep = new Mock<IDependencyProxy>();
    dep.Setup(mk => mk.Foo()).Returns("bar");
    var client = new MyRevisedClass(dep.Object);
    Assert.AreEqual("bar", client.MyFunc());
}