简体   繁体   English

C#创建一个匿名类

[英]C# create a anonymous class

So my request may be strange. 所以我的要求可能很奇怪。

Lets say I have a class CheckoutPage . 可以说我有一个CheckoutPage类。 I want a "property" Button that has the following: 我想要一个具有以下内容的“属性” Button

  • Methods Displayed() and Click() 方法Displayed()Click()
  • Property Text with a custom getter 具有自定义吸气剂的属性Text
  • Private constant locator that is an xpath to be used in the above methods 私有常量locator ,它是在上述方法中使用的xpath

These should be accessed in the following way ( checkoutPage is an instance of CheckoutPage): 应该以以下方式访问它们( checkoutPage是CheckoutPage的实例):

  • checkoutPage.Button.Click()

  • checkoutPage.Button.Displayed()

  • checkoutPage.Button.Text

One way of accomplishing this is to create a Button class and have: 实现此目的的一种方法是创建一个Button类并具有:

public class Button{
    const string locator = "BUTTON_LOCATOR";
    private SeleniumDriver Driver;

    public Checkout(SeleniumDriver driver){
        this.Driver = driver;
    }

    public string Text{
        get {
            return Driver.FindElement(locator).Text;
        }
    }

    public bool Displayed(){
        return Driver.FindElement(locator).Displayed;
    }

    public void Click(){
        var button = Driver.FindElement(locator);
        new Actions(Driver).Click(button).Perform();
    }
}

public class CheckoutPage{
    private SeleniumDriver Driver;
    public Button Button;

    public CheckoutPage(SeleniumDriver driver){
        this.Driver = driver;
        this.Button = new Button(Driver);
    }
}

However this specific button class will only be used once and I don't want to have a class sitting around for each individual button on the page. 但是,此特定的按钮类将仅使用一次,并且我不想在页面上的每个按钮旁都有一个类。 So is there another way of doing this that preserves the CheckoutPage.Button.Something interface? 那么还有另一种方法可以保留CheckoutPage.Button.Something接口吗? Also would it be possible to not have to instantiate this 也有可能不必实例化此

Maybe something similar to: 也许类似于:

public class CheckoutPage{
    private SeleniumDriver Driver;

    public CheckoutPage(SeleniumDriver driver){
        this.Driver = driver;
    }

    public object Button {
        const string locator = "BUTTON_LOCATOR";

        public bool Displayed(){
            return Driver.FindElement(locator).Displayed;
        }

        public void Click(){
            var button = Driver.FindElement(locator);
            new Actions(Driver).Click(button).Perform();
        }

        public string Text{
            get {
                return Driver.FindElement(locator).Text;
            }
        }
    }
}

The deal with anonymous types is that they are always of local scope; 匿名类型的处理方法是它们始终在本地范围内。 a method can't return an anonymous type, for example, except by casting it to a named type (eg object ). 例如,一种方法不能返回匿名类型,除非将其强制转换为命名类型(例如object )。 That isn't very useful, because the caller won't have access to the type, so you won't get intellisense, early binding, or type safety. 这不是很有用,因为调用者将无法访问该类型,因此您将不会获得智能感知,早期绑定或类型安全性。

The only workaround is to declare the type in the calling code and ask the method being called to use that as a template. 唯一的解决方法是在调用代码中声明类型,并要求被调用的方法将其用作模板。 For example, this would work: 例如,这将起作用:

public class Page
{
    public T Button<T>(T template) where T : class
    {
        return (T)Activator.CreateInstance
        (
            typeof(T), 
            new object[] 
            { 
                "Button text", 
                new Action(() => Console.WriteLine("This is a click handler")), 
                false 
            } 
        );
    }
}


public class Program
{
    static public void Main()
    {
        var template = new 
        { 
            Text = (string)null, 
            Click = (Action)null, 
            Displayed = false 
        } ;

        var page = new Page();
        var b = page.Button( template );

        Console.WriteLine(b.Text);
        Console.WriteLine(b.Displayed);
        b.Click();
    }
}

Output: 输出:

Button text
False
This is a click handler

Of course, if you pass it the wrong template, it will blow up. 当然,如果您给它传递了错误的模板,它将被炸掉。

I honestly doubt this sort of approach, or this line of thinking, will produce a cleaner or clearer solution than simply declaring a small class with three properties and returning it, as you are really supposed to. 老实说,我怀疑这种方法或这种思路是否会产生更干净或更清晰的解决方案,而不是像您真正应该的那样简单地声明一个具有三个属性的小类并返回它。

I wouldn't recommend this method, at least as you have described it. 我不推荐这种方法,至少您已经描述过了。 The page object model is supposed to present an API to the consumer... a list of actions that can be accomplished on the page and not individual elements, eg buttons. 页面对象模型应该为消费者提供一个API……一系列可以在页面上完成的动作列表,而不是单个元素(例如按钮)。 The LoginPage page object should present the Login(string username, string password) method and not the username , password , and loginButton elements. LoginPage页面对象应显示Login(string username, string password)方法,而不是usernamepasswordloginButton元素。

If you wanted to use this Button class that you are describing as an internal class that is used within a page object, that would better fit the page object model. 如果要使用此Button类(您将其描述为在页面对象内使用的内部类),则更好地适合页面对象模型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM