2015-09-17 3 views
0

Мы в .net 3.5. Я хотел бы обеспечить определенные методы (или классы) в одной сборке, чтобы доступ к ней мог получить только другая конкретная сборка. Назовём их потребитель и поставщикСпособ доступа к определенной сборке

Один из способов я знаю, с помощью StrongNameIdentityPermissionAttribute. Проблема в том, что мы не подписываем наши собрания. Подписание этого приведет к разрыву ада.

Другой способ - в коде с использованием Assembly.GetCallingAssembly().FullName. И проверьте имя для соответствия. При этом я должен кодировать в каждом методе, по крайней мере, вызов метода многократного использования. ОК.

И, конечно, есть InternalsVisibleTo, но это не то, на чем мы хотим основываться.

Есть ли другой способ реализовать что-то подобное на уровне класса или уровне метода, предпочтительно на основе атрибутов? Я имею в виду существующие возможности платформы. Я могу разработать свои собственные атрибуты - без сомнения.

ответ

1

Одна из возможностей заключается в использовании метода GetCallingAssembly, упомянутого выше, в сочетании с Windsor Castle Proxy с перехватчиком. Вы должны пометить свои методы атрибутом, оставить классы как внутренние и разоблачить конструкцию через фабрику, которая обрабатывает прокси-сервер и перехватчик (это требует от вас сделать внутренности видимыми для DynamicProxyGenAssembly2). Потребителю вашего кода не нужно делать ничего особенного, и он будет кидать при вызове. Его ошибка времени выполнения, которая не велика, но делает то, что вам нужно.

Грубая реализация будет выглядеть примерно так:

[TestFixture] 
public class Foo 
{ 
    [Test] 
    public void Should_throw() 
    { 
     var nonProxyService = new Service(); 
     nonProxyService.MethodWithSpecialPermissions().Should().BeTrue(); 
     var interceptor = new PermissionInterceptor(); 
     var generator = new ProxyGenerator(); 
     var proxyService = (IService)generator.CreateClassProxy(
       typeof(Service), new Type[] { typeof(IService) }, new IInterceptor[] { interceptor }); 
     Assert.Throws<InvalidOperationException>(() => proxyService.MethodWithSpecialPermissions()); 
    } 
} 

public interface IService 
{ 
    [SpecialPermissionAttribute] 
    bool MethodWithSpecialPermissions(); 
} 

public class SpecialPermissionAttribute : Attribute 
{ 
} 

public class Service : IService 
{ 

    public bool MethodWithSpecialPermissions() 
    { 
     return true; 
    } 
} 

public class PermissionInterceptor : IInterceptor 
{ 
    public void Intercept(IInvocation invocation) 
    { 
     if (invocation.Method.HasAttribute<SpecialPermissionAttribute>() 
      && Assembly.GetCallingAssembly().FullName != "foo") 
     { 
      throw new InvalidOperationException(); 
     } 
     invocation.Proceed(); 
    } 
} 

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

+0

Я ценю ваше время. Но я думаю, что это не нужно. В моей ситуации мне нужно защитить некоторые классы от доступа всеми, кроме одной сборки. Хорошо, может быть 2-й тест тоже. Я могу создать базовый класс с конструктором, который вызывает 'Assembly.GetCallingAssembly(). FullName' и исключение исключения" вам не разрешено использовать этот класс ". Мы не нацеливаем защиту от хакеров, это связано с прямым доступом к консультанту/разработчику. Лучше всего было бы отрицать видимость класса во время разработки вообще. –

+1

Полностью понятно. Прокси - это довольно сложная задача. Насколько я знаю, нет способа отрицать видимость во время компиляции, кроме InternalsVisibleTo, это предел языка. Общественность - это все или ничего. Если вы хотите, чтобы решение AoP использовало атрибуты Castle Dynamic Proxy, это довольно стандартное решение (используется многими библиотеками, например, nhibernate). В противном случае решение базового класса работает хорошо. Другой вариант - это вложенная зависимость, которая выполняет валидацию сборки звонков (из школы мысли о структуре над наследством). – JCalder

+0

+1 для хорошей цели. Введенная зависимость, вероятно, не будет работать, потому что потребитель может отправить свой собственный «обработчик зависимостей». Но это именно то, чего я не хочу. Мы хотим обеспечить соблюдение конкретного правила. Одна вещь, которую мы можем сделать, - это установить список разрешенных сборок в общей вертикальной сборке, которые не затрагиваются консультантами, и выполнять проверку в базе. –

Смежные вопросы