You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#运行时动态切换命名空间调用设备方法的实现咨询

Solution to Dynamic Cash Machine Method Calls in C#

Absolutely, you can ditch those verbose namespace references and clunky switch statements—this is exactly the kind of scenario where abstraction and design patterns make C# code clean and maintainable. Let’s walk through two practical approaches, starting with the most recommended one.


1. Interface-Based Abstraction (Type-Safe & Idiomatic)

This is the go-to solution because it keeps your code type-safe, easy to extend, and free of repetitive switch logic. Here’s how to set it up:

Step 1: Define a Common Interface

First, create an interface that standardizes the core methods all cash machines share. This acts as a contract for every vendor’s implementation:

public interface ICashMachine
{
    void Deposit();
    void Dispense();
}

Step 2: Implement the Interface for Each Vendor

Update each vendor’s class to implement ICashMachine. This lets you treat all machines the same way, regardless of their namespace:

namespace MyProject.A
{
    public class MachineA : ICashMachine
    {
        public void Deposit()
        {
            // Vendor A's specific deposit logic here
        }

        public void Dispense()
        {
            // Vendor A's specific dispense logic here
        }
    }
}

// Repeat this pattern for MachineB, MachineC, MachineD in their respective namespaces

Step 3: Use a Factory to Retrieve Instances

Instead of a switch statement, use a factory class to get the correct machine instance based on your current device type. This centralizes the mapping and makes adding new vendors (like Vendor E) trivial:

public static class CashMachineFactory
{
    public static ICashMachine GetMachine(string machineType)
    {
        // You can even load this mapping from a config file instead of hardcoding
        return machineType switch
        {
            "A" => new MyProject.A.MachineA(),
            "B" => new MyProject.B.MachineB(),
            "C" => new MyProject.C.MachineC(),
            "D" => new MyProject.D.MachineD(),
            _ => throw new ArgumentException($"Unknown machine type: {machineType}")
        };
    }
}

Step 4: Call Methods Cleanly

Now you can call Deposit() directly, no namespace or switch required:

// Get the current machine type from your config or connection state
string currentMachine = "A"; // Example value from your app's state

ICashMachine machine = CashMachineFactory.GetMachine(currentMachine);
machine.Deposit(); // Simple, clean call—no messy references!

Bonus: Dependency Injection (For Apps Like ASP.NET)

If you’re working in a DI-friendly environment (like ASP.NET Core), register the correct ICashMachine implementation at startup based on config, then inject it wherever you need it:

// In Program.cs or Startup.cs
string machineType = Configuration["CurrentCashMachine"];
switch (machineType)
{
    case "A":
        services.AddScoped<ICashMachine, MyProject.A.MachineA>();
        break;
    case "B":
        services.AddScoped<ICashMachine, MyProject.B.MachineB>();
        break;
    // Add other vendor cases here
}

// Inject the machine into your service/controller
public class CashService
{
    private readonly ICashMachine _cashMachine;

    public CashService(ICashMachine cashMachine)
    {
        _cashMachine = cashMachine;
    }

    public void ProcessCustomerDeposit()
    {
        _cashMachine.Deposit(); // Direct call with zero boilerplate
    }
}

2. Reflection (For Fully Dynamic Config)

If you need to load the machine type entirely from a config string (e.g., a full namespace + class name), reflection works. Note: This is less type-safe and has minor performance overhead, but it’s useful for scenarios where you need to switch vendors without recompiling.

Example Implementation:

// Get the full class name from config (e.g., "MyProject.A.MachineA")
string machineFullTypeName = Configuration["CashMachine:FullTypeName"];

// Load the type and create an instance
Type machineType = Type.GetType(machineFullTypeName);
if (machineType == null)
{
    throw new InvalidOperationException($"Could not find type: {machineFullTypeName}");
}

// Cast to our interface to call methods safely
ICashMachine machine = (ICashMachine)Activator.CreateInstance(machineType);
machine.Deposit();

Pro Tip: Cache the Type

To avoid repeated reflection overhead, cache the Type instance after the first load.


Final Notes

  • Stick with the interface approach for most cases—it’s type-safe, easier to debug, and aligns with C# best practices.
  • Reflection is a tool for edge cases where you need maximum dynamic flexibility.

内容的提问来源于stack exchange,提问作者Muhannad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:12:33