Więc nie ma dokładnej odpowiedzi, ale wziąłem go tak daleko, jak mogłem patrząc na niego. Myślę, że rozumiem, dlaczego to się dzieje, kiedy dziedziczą CodeAccessSecurityAttribute
i nie SecurityAttribute.
Jeśli spojrzeć na IL generowane podczas stosowania atrybutu Foo
kiedy dziedziczy CodeAccessSecurityAttribute
wygląda to tak:
.permissionset demand = {class 'ConsoleApplication1.FooAttribute, ConsoleApplication1, Version=1.0.0.0, Culture=neutral' = {}}
Kiedy Foo
dziedziczy z SecurityAttribute it wygląda tak:
.custom instance void ConsoleApplication1.FooAttribute::.ctor(valuetype [mscorlib]System.Security.Permissions.SecurityAction) = (01 00 02 00 00 00 00 00)
Oczywiście wartość CodeAccessSecurityAttribute znacznie zmienia IL wygenerowany przez zastosowanie atrybutu.
Patrząc na IL więcej, jeśli możemy zmienić deklarację Foo być jak następująco
[Foo(SecurityAction.Demand)]
Otrzymujemy następujące IL:
.permissionset demand = {class 'ConsoleApplication1.FooAttribute, ConsoleApplication1, Version=1.0.0.0, Culture=neutral' = {}}
jego samego, jak to było, kiedy nie podać opcjonalny parametr. Dodatkowo możemy spowodować błąd nie tylko przez podział atrybut i klasę na oddzielnych plikach Program
możemy doprowadzić go przez rozmieszczanie plików w klasie jak poniżej:
[Foo]
class Program
{
static void Main(string[] args) {}
}
[System.Serializable]
sealed class FooAttribute : CodeAccessSecurityAttribute
{
public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { }
public override System.Security.IPermission CreatePermission() { return null; }
}
Jeszcze bardziej interesujące, jeśli mamy następujące z klasą Other
i Other2
podać błąd, ale nie ma Program
. Tylko zajęcia, które przychodzą przed Foo
w pliku będzie miał błąd
[Foo]
class Other
{
}
[Foo]
class Other2
{
}
[System.Serializable]
sealed class FooAttribute : CodeAccessSecurityAttribute
{
public FooAttribute(SecurityAction action = SecurityAction.Demand) : base(action) { }
public override System.Security.IPermission CreatePermission() { return null; } }
[Foo]
class Program
{
static void Main(string[] args) {}
}
Co to mówi mi to, że nie jest to problem gdzieś w procesie budowania. Nie wiem wystarczająco dużo o tym, jak działa Code Access Security, aby określić, jaki jest dokładny problem. Musi być częścią procesu, który analizuje CodeAccessSecurityAttributes i robi coś z próbą zastosowania SecurityAction do kodu. Zakładam, że buduje jakieś metadane dla zespołu. Musi to zrobić w pewien uporządkowany sposób, aby nie widział parametru opcjonalnego, dopóki nie przejdzie już klasy Program. Następnie musi użyć tych metadanych w pewien sposób podczas procesu budowania i tam właśnie widzisz awarię. Aby uzyskać więcej szczegółów, będziemy musieli mieć nadzieję, że ktoś, kto zna kompilator, np. Eric, może rzucić trochę światła na to. Przekazałbym go na connect.microsoft.com jako jeden z sugerowanych komentarzy, ponieważ wygląda na to, że błąd spowodowany jest tym, że rzeczy są przemierzane.
Jaki jest związek między FooAttribute, w źródle i DebugCallTraceAttribute, w komunikacie o błędzie? –
Czy istnieje przyczyna "SecurityAttribute" w pierwszym fragmencie i "CodeAccessSecurityAttribute" w drugim? Wygląda na to, że powinny być takie same dla ważnego minimalnego przypadku testowego. (Np. Czy jest to związane z tą zmianą, czy jest w dwóch plikach lub obu?) –
przykro, jest 3 nad ranem w Moskwie, wszystkie błędy fragmentu są naprawione – ControlFlow