如何在 C# 中将 className 传递给将泛型类型作为参数的方法

发布于 2024-12-22 15:41:11 字数 2648 浏览 1 评论 0原文

我有很多类反映了 White/UIAutomation 的屏幕存储库。 要使用存储库,我需要创建许多反映应用程序窗口屏幕的类。

为了创建存储库,我使用以下方法:

var repoReport = repository.Get<MyClassRepresentingWindow>("WindowTitle", 
InitializeOption.WithCache);

它传递一个泛型类型,该类型是我准备的类。

我想要做的是创建一个 Dictionary(stringClassName, string windowTitle) 或任何映射来传递给该方法。 问题是无法像 Java ClassForName 那样传递 className。

我尝试了 System.Activator 但没有成功。

Object configObj = System.Activator.CreateInstance(c);
Type c = System.Type.GetType("Namespace.MyClassRepresentingWIndow");

var myClass = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance("Namespace.MyClassRepresentingWIndow");

Type type = assembly.GetType("Namespace.MyClassRepresentingWIndow");
object obj = Activator.CreateInstance(type);

var repoReport = repository.Get<c>("WindowTitle", 
InitializeOption.WithCache);

var repoReport = repository.Get<c.Name>("WindowTitle", 
InitializeOption.WithCache);

更新1 伙计们,我不会坐在代码前面,但我会尽力使我的问题不那么复杂。

这是我在 White 存储库中找到的一种方法,我认为我使用过: https://github.com/petmongrels/white/blob /itemsmap/Components/Repository/Source/ScreenRepository.cs

public virtual T Get<T>(string title, InitializeOption option) where T : AppScreen
    {
        ClearClosedScreens();
        AppScreen screen;
        var repositoryCacheKey = new ScreenRepositoryCacheKey(title, typeof (T));
        if (!screenCache.TryGetValue(repositoryCacheKey, out screen))
        {
            Window window = applicationSession.Application.GetWindow(title, IdentifiedOption<T>(option));
            screen = GetScreen<T>(window);
            screenCache.Add(repositoryCacheKey, screen);
        }

        if (screen != null)
            sessionReport.Next(typeof (T));
        return (T) screen;
    }

我记得 VS 显示为 .Get 作为 .Get<"class" type>。很抱歉我无法更好地表达自己。请有一位病人和我一起,因为我不熟悉这个术语。

Update2

最后我想得到这样的结果:

var repoReport1 = repository.Get<MyClassRepresentingWindow1>("WindowTitle", InitializeOption.WithCache);
var repoReport1 = repository.Get<MyClassRepresentingWindow2>("WindowTitle", InitializeOption.WithCache);
var repoReport1 = repository.Get<MyClassRepresentingWindow3>("WindowTitle", InitializeOption.WithCache);

我有一个 MyClassRepresentingWindow{1,2,3} 代码。我只是不知道如何将类名传递给 Get 方法。输入时我有这个类的字符串名称。在输出时,我想提供此方法 .Get 可以获得的东西。 我希望你现在能理解我。

I have lots of classes reflecting my screen Repository from White/UIAutomation.
To use repository I need to create lots of classes that reflect screens of my application windows.

To create a repository I use the following method:

var repoReport = repository.Get<MyClassRepresentingWindow>("WindowTitle", 
InitializeOption.WithCache);

it passes a generic type which is a Class I prepared.

What I want to do is to create a Dictionary(stringClassName, string windowTitle) or any Map to pass to that method.
The problem is can't pass className like in Java ClassForName.

I tried System.Activator but without any success.

Object configObj = System.Activator.CreateInstance(c);
Type c = System.Type.GetType("Namespace.MyClassRepresentingWIndow");

var myClass = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance("Namespace.MyClassRepresentingWIndow");

Type type = assembly.GetType("Namespace.MyClassRepresentingWIndow");
object obj = Activator.CreateInstance(type);

var repoReport = repository.Get<c>("WindowTitle", 
InitializeOption.WithCache);

var repoReport = repository.Get<c.Name>("WindowTitle", 
InitializeOption.WithCache);

Update1
Guys, I'm not sitting in front of the code but I'll try to make my question less complicate.

This is a method which I found in the White repository that I think I use:
https://github.com/petmongrels/white/blob/itemsmap/Components/Repository/Source/ScreenRepository.cs

public virtual T Get<T>(string title, InitializeOption option) where T : AppScreen
    {
        ClearClosedScreens();
        AppScreen screen;
        var repositoryCacheKey = new ScreenRepositoryCacheKey(title, typeof (T));
        if (!screenCache.TryGetValue(repositoryCacheKey, out screen))
        {
            Window window = applicationSession.Application.GetWindow(title, IdentifiedOption<T>(option));
            screen = GetScreen<T>(window);
            screenCache.Add(repositoryCacheKey, screen);
        }

        if (screen != null)
            sessionReport.Next(typeof (T));
        return (T) screen;
    }

As I remember VS displayed .Get as a .Get<"class" type>. I'm sorry I can't express myself better. Please have a patient with me because I'm not familiar with this terminology.

Update2

At the end I want to get something like this:

var repoReport1 = repository.Get<MyClassRepresentingWindow1>("WindowTitle", InitializeOption.WithCache);
var repoReport1 = repository.Get<MyClassRepresentingWindow2>("WindowTitle", InitializeOption.WithCache);
var repoReport1 = repository.Get<MyClassRepresentingWindow3>("WindowTitle", InitializeOption.WithCache);

And I have a code of MyClassRepresentingWindow{1,2,3}. I just don't know how to pass class name to Get method. On input I have a string name of this class. On output I want to deliver something that this method .Get<T> can get.
I hope you can understand me now.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

话少情深 2024-12-29 15:41:11

为了使用变量类型参数调用它,其值仅在运行时才知道,您需要使用反射。我假设您知道如何获取表示存储库的 Get 方法的 MethodInfo

一旦您了解了这一点,此示例将说明如何使用 MethodInfo 对象的基本思想。该示例假设 repository 类名为 Repo;根据需要进行更改:

object InvokeGenericMethod(Repo repository, MethodInfo method, Type typeArg, string arg1, InitializeOption arg2)
{
    MethodInfo constructedMethod = method.MakeGenericMethod(typeArg);
    return constructedMethod.Invoke(repository, new object[] { arg1, arg2 });
}

当然,您可以使其更加通用,但这会使示例变得不太清晰。

In order to call this with a variable type argument, whose value is only known at run time, you need to use reflection. I assume that you know how to get the MethodInfo representing the repository's Get<T> method.

Once you have that, this example illustrates the basic idea how to use the MethodInfo object. The example assumes that the repository class is called Repo; change that as needed:

object InvokeGenericMethod(Repo repository, MethodInfo method, Type typeArg, string arg1, InitializeOption arg2)
{
    MethodInfo constructedMethod = method.MakeGenericMethod(typeArg);
    return constructedMethod.Invoke(repository, new object[] { arg1, arg2 });
}

You could make this more generic, of course, but that would have made the example less clear.

浮华 2024-12-29 15:41:11

我相信您想要的是这样的:

    public string GetName<T>()
    {
        return typeof(T).Name;
    }

这会导致以下单元测试通过(“基本数学”只是我在草稿应用程序中放置的一种类型):

    [TestMethod]
    public void Test_Of_Generic_Type_Name()
    {
        var myBuilder = new GenericNamer();

        Assert.AreEqual<string>("BasicMath", myBuilder.GetName<BasicMath>());
    }

您还可以使用该类型的全名、程序集等以下是有关使用反射从 Type 类中提取内容的更多信息:

http://msdn.microsoft.com/en-us/library/system.type.aspx

I believe what you want is something like this:

    public string GetName<T>()
    {
        return typeof(T).Name;
    }

That causes the following unit test to pass (the "Basic Math" is just a type I had laying around in my scratch application):

    [TestMethod]
    public void Test_Of_Generic_Type_Name()
    {
        var myBuilder = new GenericNamer();

        Assert.AreEqual<string>("BasicMath", myBuilder.GetName<BasicMath>());
    }

You could also use the type's full name, assembly, etc. Here's some more information on what you can pull out of the Type class using reflection:

http://msdn.microsoft.com/en-us/library/system.type.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文