Опции для информирования Потока для остановки

Это - дополнительный метод для ASP.NET вспомогательный метод ссылки действия MVC, который позволяет, это для использования контроллера разрешает атрибуты решать, должна ли ссылка быть включена, отключена или скрыта от представления текущего пользователя. Я сохраняю Вас от необходимости включить Ваши ограниченные действия в то, "если" пункты, которые проверяют на пользовательское членство во всех представлениях. Благодаря Maarten Balliauw для идеи и битов кода, которые показали мне путь:)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Principal;
using System.Web.Routing;
using System.Web.Mvc;
using System.Collections;
using System.Reflection;
namespace System.Web.Mvc.Html
{
    public static class HtmlHelperExtensions
    {

        /// 
        /// Shows or hides an action link based on the user's membership status
        /// and the controller's authorize attributes
        /// 
        /// The link text.
        /// The controller action name.
        /// The controller name.
        /// 
        public static string SecurityTrimmedActionLink(
            this HtmlHelper htmlHelper,
            string linkText,
            string action,
            string controller)
        {
            return SecurityTrimmedActionLink(htmlHelper, linkText, action, controller, false, null);
        }

        /// 
        /// Enables, disables or hides an action link based on the user's membership status
        /// and the controller's authorize attributes
        /// 
        /// The link text.
        /// The action name.
        /// The controller name.
        /// if set to true [show link as disabled - 
        /// using a span tag instead of an anchor tag ].
        /// Use this to add attributes to the disabled
        /// span tag.
        /// 
        public static string SecurityTrimmedActionLink(
            this HtmlHelper htmlHelper, 
            string linkText, 
            string action, 
            string controller, 
            bool showDisabled, 
            string disabledAttributeText)
        {
            if (IsAccessibleToUser(action, controller, HttpContext.Current ))
            {
                return htmlHelper.ActionLink(linkText, action, controller);
            }
            else
            {
                return showDisabled ? 
                    String.Format(
                        "{0}", 
                        linkText, 
                        disabledAttributeText==null?"":" "+disabledAttributeText
                        ) : "";
            }
        }

        private static IController GetControllerInstance(string controllerName)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            Type controllerType = GetControllerType(controllerName);
            return (IController)Activator.CreateInstance(controllerType);
        }

        private static ArrayList GetControllerAttributes(string controllerName, HttpContext context)
        {
            if (context.Cache[controllerName + "_ControllerAttributes"] == null)
            {
                var controller = GetControllerInstance(controllerName);

                context.Cache.Add(
                    controllerName + "_ControllerAttributes",
                    new ArrayList(controller.GetType().GetCustomAttributes(typeof(AuthorizeAttribute), true)),
                    null,
                    Caching.Cache.NoAbsoluteExpiration,
                    Caching.Cache.NoSlidingExpiration,
                    Caching.CacheItemPriority.Default,
                    null);

            }
            return (ArrayList)context.Cache[controllerName + "_ControllerAttributes"];

        }

        private static ArrayList GetMethodAttributes(string controllerName, string actionName, HttpContext context)
        {
            if (context.Cache[controllerName + "_" + actionName + "_ActionAttributes"] == null)
            {
                ArrayList actionAttrs = new ArrayList();
                var controller = GetControllerInstance(controllerName);
                MethodInfo[] methods = controller.GetType().GetMethods();

                foreach (MethodInfo method in methods)
                {
                    object[] attributes = method.GetCustomAttributes(typeof(ActionNameAttribute), true);

                    if ((attributes.Length == 0 && method.Name == actionName)
                        ||
                        (attributes.Length > 0 && ((ActionNameAttribute)attributes[0]).Name == actionName))
                    {
                        actionAttrs.AddRange(method.GetCustomAttributes(typeof(AuthorizeAttribute), true));
                    }
                }

                context.Cache.Add(
                    controllerName + "_" + actionName + "_ActionAttributes",
                    actionAttrs,
                    null,
                    Caching.Cache.NoAbsoluteExpiration,
                    Caching.Cache.NoSlidingExpiration,
                    Caching.CacheItemPriority.Default,
                    null);

            }

            return (ArrayList)context.Cache[controllerName + "_" + actionName+ "_ActionAttributes"]; 
        }

        public static bool IsAccessibleToUser(string actionToAuthorize, string controllerToAuthorize, HttpContext context)
        {
            IPrincipal principal = context.User;

            //cache the attribute list for both controller class and it's methods

            ArrayList controllerAttributes = GetControllerAttributes(controllerToAuthorize, context);

            ArrayList actionAttributes = GetMethodAttributes(controllerToAuthorize, actionToAuthorize, context);                        

            if (controllerAttributes.Count == 0 && actionAttributes.Count == 0)
                return true;

            string roles = "";
            string users = "";
            if (controllerAttributes.Count > 0)
            {
                AuthorizeAttribute attribute = controllerAttributes[0] as AuthorizeAttribute;
                roles += attribute.Roles;
                users += attribute.Users;
            }
            if (actionAttributes.Count > 0)
            {
                AuthorizeAttribute attribute = actionAttributes[0] as AuthorizeAttribute;
                roles += attribute.Roles;
                users += attribute.Users;
            }

            if (string.IsNullOrEmpty(roles) && string.IsNullOrEmpty(users) && principal.Identity.IsAuthenticated)
                return true;

            string[] roleArray = roles.Split(',');
            string[] usersArray = users.Split(',');
            foreach (string role in roleArray)
            {
                if (role == "*" || principal.IsInRole(role))
                    return true;
            }
            foreach (string user in usersArray)
            {
                if (user == "*" && (principal.Identity.Name == user))
                    return true;
            }
            return false;
        }

        private static Type GetControllerType(string controllerName)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            foreach (Type type in assembly.GetTypes())
            {
                if (
                    type.BaseType!=null 
                    && type.BaseType.Name == "Controller" 
                    && (type.Name.ToUpper() == (controllerName.ToUpper() + "Controller".ToUpper())))
                {
                    return type;
                }
            }
            return null;
        }

    }
}

6
задан Ralph Shillington 30 July 2009 в 18:30
поделиться

6 ответов

Это лучший подход, чем пытаться установить ThreadState. Если вы посмотрите документацию для ThreadState , там конкретно сказано, что StopRequested предназначен только для внутреннего использования.

Установка логического значения из другого потока - безопасная операция. В этом случае блокировка не требуется.

3
ответ дан 9 December 2019 в 22:38
поделиться

Вы можете использовать BackgroundWorker , чтобы сделать эту работу за вас, используя RunWorkerAsync () и обрабатывая работника . CancellationPending == true в вашей логике.

BackgroundWorker worker = new BackgroundWorker();
worker.WorkerSupportsCancellation = true;
worker.DoWork += MyWorkFunction;
worker.RunWorkerCompleted += MyWorkDoneSuccessfullyFunction;
worker.RunWorkerAsync();

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

private volatile bool cancelWork = false;

public void CancelWork()
{
  cancelWork = true;
}
3
ответ дан 9 December 2019 в 22:38
поделиться

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

2
ответ дан 9 December 2019 в 22:38
поделиться

Меня беспокоит то, что StopRequested получает значение True на другой поток. Это безопасно?

Убедитесь, что в поле StopRequested есть ключевое слово volatile . См. этот другой ответ , чтобы узнать причину этого.

1
ответ дан 9 December 2019 в 22:38
поделиться

Вы можете использовать Thread.Abort () и заключить любую необходимую очистку в метод DoWork () в блок finally.

2
ответ дан 9 December 2019 в 22:38
поделиться

Если вы используете BackgroundWorker , вы должны вызвать функцию CancelAsync BackgroundWorker, которая устанавливает для свойства CancellationPending значение true, это то, что вы должны искать в своем цикле:

public void Run(object sender, DoWorkEventArgs e)   
{      
   BackgroundWorker worker = sender as BackgroundWorker;
   if(worker != null)
   {
      while (!worker.CancellationPending)   
      {
         DoWork();  
      }
   }
}

Выше будет код события DoWork , который вызывается при запуске функции RunWorkerAsync .

0
ответ дан 9 December 2019 в 22:38
поделиться
Другие вопросы по тегам:

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