Существует ли способ, которым я могу осуществить метод для следования за определенной сигнатурой метода?

Ниже приведено решение на языке JavaScript с использованием синтаксиса ES6.

Stack.js

//stack using array
class Stack {
  constructor() {
    this.data = [];
  }

  push(data) {
    this.data.push(data);
  }

  pop() {
    return this.data.pop();
  }

  peek() {
    return this.data[this.data.length - 1];
  }

  size(){
    return this.data.length;
  }
}

export { Stack };

QueueUsingTwoStacks.js

import { Stack } from "./Stack";

class QueueUsingTwoStacks {
  constructor() {
    this.stack1 = new Stack();
    this.stack2 = new Stack();
  }

  enqueue(data) {
    this.stack1.push(data);
  }

  dequeue() {
    //if both stacks are empty, return undefined
    if (this.stack1.size() === 0 && this.stack2.size() === 0)
      return undefined;

    //if stack2 is empty, pop all elements from stack1 to stack2 till stack1 is empty
    if (this.stack2.size() === 0) {
      while (this.stack1.size() !== 0) {
        this.stack2.push(this.stack1.pop());
      }
    }

    //pop and return the element from stack 2
    return this.stack2.pop();
  }
}

export { QueueUsingTwoStacks };

Ниже приведено использование:

index.js

import { StackUsingTwoQueues } from './StackUsingTwoQueues';

let que = new QueueUsingTwoStacks();
que.enqueue("A");
que.enqueue("B");
que.enqueue("C");

console.log(que.dequeue());  //output: "A"
5
задан Hao 30 June 2009 в 02:04
поделиться

6 ответов

Вы можете реализовать как FollowAttribute , который вы используете в своем примере, и пишите правило статического анализа (скажем, FxCop) , которое может проверять, имеет ли какой-либо метод, помеченный этим атрибутом, ту же сигнатуру, что и упомянутый делегат. Так что это должно быть возможно.

3
ответ дан 18 December 2019 в 10:48
поделиться

Другие ответы, очевидно, верны, но ничто не защитит вас от того, чтобы вы забыли применить атрибут [Follow (AutoCompleteDelegate)] в вашем методе.

Я думаю, вам было бы лучше выключить превращение методов в классы, реализующие интерфейс:

public interface IAutoComplete
{
    DataSet Complete(string filter, long rowOffset);
}

public class CustomerAutoComplele : IAutoComplete
{
    public DataSet Complete(string filter, long rowOffset)
    {
        var c = Connect();
        // some code here
    }
}

, а затем использовать шаблон фабричного метода , чтобы получить свои «автозаполнители»:

public static class AutoCompleteFactory
{
    public static IAutoComplete CreateFor(string purpose)
    {
        // build up and return an IAutoComplete implementation based on purpose.
    }
}

или

public static class AutoCompleteFactory
{
    public static IAutoComplete CreateFor<T>()
    {
        // build up and return an IAutoComplete implementation based on T which
        // could be Customer, Item, BranchOffice class.
    }
}

. посмотрите на инверсию управления и внедрение зависимостей, чтобы избежать жесткого кодирования списка реализаций автозаполнения в вашем заводском методе.

11
ответ дан 18 December 2019 в 10:48
поделиться

Это не языковая функция, но ...

Это то, что вы могли бы сделать для проверки: написать модульные тесты, которые отражаются на классе и терпят неудачу, если подпись не соответствовать объявлению атрибута.

PostSharp также дает вам несколько интересных возможностей для этого при компиляции. Не знаю, как именно вы его использовали бы, но подозреваю, что вы могли бы ...

1
ответ дан 18 December 2019 в 10:48
поделиться

Я бы спросил, зачем вам это нужно. Если вы не хотите, чтобы класс изменялся посредством наследования, вы можете сделать его запечатанным классом. Если вы беспокоитесь о том, что кто-то сменит класс в будущем, у вас есть один из двух случаев. 1) Они не понимают, что делают; ничто не может помешать плохому программисту делать плохие вещи, если они имеют полное право редактировать текст программы. 2) Они расширяют функциональность класса таким образом, который вы в настоящее время не понимаете, что вредит повторному использованию.

1
ответ дан 18 December 2019 в 10:48
поделиться

Атрибуты сохраняются как дополнительная метаинформация во время компиляции - вы можете запрашивать их во время выполнения, но во время компиляции они не учитываются.

Вы не можете ограничить метод с помощью атрибут на нем. Вы можете ограничить способ применения атрибута (т.е. только для методов или может быть применено более одного).

Я бы предложил использовать FxCop для предупреждения, когда атрибуты не совпадают - если вы действительно будете осторожны с способом события поддерживают приведение типов:

[Follow(AutoCompleteDelegate)]
public DataSet Customer_AutoComplete(string filter, int rowOffset)

Будет допустимым делегатом.

0
ответ дан 18 December 2019 в 10:48
поделиться

Нет.

Типа.

Вы не можете получить такое поведение во время компиляции. С помощью атрибутов вы можете вставить это в простую тестовую оснастку или вызвать немедленный сбой при создании экземпляра содержащего класса.

Рассмотрим два (быстро взломанных) атрибута:

[AttributeUsage(AttributeTargets.Class)]
public class EnforceConforms : Attribute
{
    public EnforceConforms(Type myClass)
        : base()
    {
        MethodInfo[] info = myClass.GetMethods();

        foreach (MethodInfo method in info)
        {
            object[] objs = method.GetCustomAttributes(false);

            foreach (object o in objs)
            {
                Attribute t = (Attribute)o;

                if (t.GetType() != typeof(ConformsAttribute)) continue;

                MethodInfo mustConformTo = ((ConformsAttribute)t).ConformTo;

                ParameterInfo[] info1 = mustConformTo.GetParameters();
                ParameterInfo[] info2 = method.GetParameters();

                bool doesNotCoform = false;

                doesNotCoform |= (mustConformTo.ReturnType != method.ReturnType);
                doesNotCoform |= (info1.Length != info2.Length);

                if (!doesNotCoform)
                {
                    for (int i = 0; i < info1.Length; i++)
                    {
                        ParameterInfo p1 = info1[i];
                        ParameterInfo p2 = info2[i];

                        if (!p1.ParameterType.Equals(p2.ParameterType))
                        {
                            doesNotCoform = true;
                            break;
                        }
                    }
                }

                if (doesNotCoform)
                {
                    throw new Exception(myClass.Name + "." + method.Name + " does not conform to required delegate signature");
                }
            }
        }
    }
}

[AttributeUsage(AttributeTargets.Method)]
public class ConformsAttribute : Attribute
{
    public MethodInfo ConformTo;

    public ConformsAttribute(Type type)
        : base()
    {
        if (type.BaseType != typeof(Delegate) && type.BaseType != typeof(System.MulticastDelegate)) throw new Exception("Can only accept delegates");

        ConformTo = type.GetMethod("Invoke");
    }
}

Throw EnforceConforms (typeof (myFavoriteClass)) на class и Conforms (typeof (myFavoriteDelegate)) в соответствующие методы и , затем (это хакерская часть) typeof (myFavoriteClass) .GetCustomAttributes (false). Вы можете сделать это в статическом инициализаторе, чтобы сбой "очень быстро", или сделать это в тестовом классе (который ищет все методы в сборке с атрибутом EnforceConforms, если вы хотите придумать что-то необычное).

Как правило, вам, вероятно, не следует этого делать. не использую это. Если ваш дизайн требует, чтобы вы проверили правильные реализации делегирования, вам следует по возможности перестроить архитектуру. Плюс биты времени, не связанные с компиляцией, заставляют вас не сильно экономить время.

0
ответ дан 18 December 2019 в 10:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: