I have a class from a third-party assembly (so I can't edit it):
public class MyClass
{
private bool _loggedIn;
public void Login() {_loggedIn = true;}
public void Logout() {
if (!_loggedIn) throw new InvalidOperationException();
_loggedIn = false;
}
}
Now, suppose I have an instance of MyClass (for which I don't know _loggedIn), and I need call LogOut. Which of the following methods of avoiding a fatal exception will generally be faster? (any other method would be fine too):
To call LogOut, and if _loggedIn == false, just catch the exception
To use reflection to check that _loggedIn == true, and only call LogOut if so
It depends on the invariants you expect to see in your application.
1. If you expect to have a lot of MyClass having different state(logged in, logged off), then it is better to avoid overhead of exception (because exception is Exceptional situation) and use some specific public IsLoggedIn property (obviously to avoid Reflection) or some TryXxxxx-like methods.
And even if you can't modify the original code no one stops you from wrapping it:
public class MyWrappedClass
{
public Boolean IsLoggedIn {get; private set;}
private MyClass m_Log;
public MyWrappedClass ()
{
this.m_Log = new MyClass();
this.IsLoggedIn = false;
}
public void Log()
{
try
{
this.m_Log.LogIn();
this.IsLoggedIn = true;
}
catch
{
this.IsLoggedIn = false;
}
}
public void LogOut()
{
try
{
this.m_Log.LogOut();
this.IsLoggedIn = false;
}
catch
{
this.IsLoggedIn = true;
}
}
}
You could even go further and implement IDisposable interface with it to avoid manual LogIn-LogOut management:
public class MyWrappedClass
{
private class LogSessionToken : IDisposable
{
private MyWrappedClass parent;
public LogSessionToken (MyWrappedClass parent)
{
parent.LogIn();
}
public void Dispose()
{
parent.LogOut();
}
}
public IDisposable LogSession()
{
return new LogSessionToken (this);
}
// ...
}
And use it like
using (var logToken = wrappedInstance.LogSession)
{
// do the work.
} // No need to worry about manual LogOut
2. If you expect to use only few of MyClass in a proper fashion, then it would be a better idea to not handle exception at all - if something wrong happened then it is some programming error thus the program shall be terminated.
First, if your class doesn't expose at least a read-only property for LoggedIn, there sounds like a fairly large design flaw.
For speed, using reflection will generally be faster, particularly if you cache the FieldInfo or build a Func<bool> using System.Linq.Expressions. This is because Exceptions collect lots of debug information when thrown, including a StackTrace, which can be expensive.
As with anything, though, it is often best to test such operations, as there are sometime optimizations or other factors that may surprise you.
If the pattern if (CanFoo) Foo(); appears very much, that tends to imply very strongly that either:
A properly-written client would know when it can or cannot call Foo. The fact that a client doesn't know suggest that it's probably deficient in other ways.
The class exposing CanFoo and Foo should also expose a method which will Foo if possible and appropriate (the method should throw if unable to establish expected post-conditions, but should return silently if the post-conditions were established before the call)
In cases where a class one does not control should provide such a method but doesn't, the cleanest approach may be to write one's own wrapper method whose semantics mirror those the missing method should have had. If a later version of the class implements the missing method, changing one's code to use that implementation may be easier than refactoring lots of if (CanFoo) constructs.
BTW, I would suggest that a properly-designed class should allow calling code to indicate whether it is expecting a transition from logged-in state to logged-out state, or whether it wants to end up in logged-out state but it doesn't care how it gets there. Both kinds of semantics have perfectly legitimate uses; in cases where the first kind would be appropriate, having a LogOut method throw an exception if called on a closed session would be a good thing, but in cases where client code merely wants to ensure that it is logged out, having an EnsureLoggedOut method that could be invoked unconditionally would be cleaner than having to add extra client-side code for that purpose.
Related
I'm building a retry system that allows me to attempt code multiple times before giving up (useful for things like establishing connections over the network). With this, the basic code I usually copy and paste everywhere as a base is:
for (int i = 0; i < attemptThreshold; i++) {
try {
...
break;
} catch (Exception ex) { ... }
}
There's quite a bit of logging code within the try and catch blocks that can be delegated by refactoring to ensure consistency. It's straightforward to refactor it and delegate the work of retrying:
public static class DelegateFactory {
public static bool DelegateWork<TIn, TOut>(Func<TIn, TOut> work, int attemptThreshold, TIn input, out TOut output) {
if (work == null)
throw new ArgumentException(...);
for (int i = 0; i < attemptThreshold; i++) {
try {
OnMessageReceived?.Invoke(work, new FactoryEventArgs("Some message..."));
output = work(input);
return true;
} catch (Exception e) { OnExceptionEncountered?.Invoke(work, new FactoryEventArgs(e)); }
}
return false;
}
public static event EventHandler<FactoryEventArgs> OnMessageReceived;
public static event EventHandler<FactoryEventArgs> OnExceptionEncountered;
}
Calling it is also straightforward:
DelegateFactory.DelegateWork((connectionString) => {
using (SqlConnection conn = new SqlConnection(connectionString))
conn.Open();
}, 10, "ABC123", out bool connectionMade);
Console.WriteLine($"Connection Made: {(connectionMade ? "Yes" : "No")}");
Keep in mind, the above code excludes the definition for FactoryEventArgs, but it's just a class that takes an object as an argument (for simplicity in prototyping). Now, what I have above works just fine, but I wanted to add a way to allow the caller to post messages using an event for the factory's subscriber to log (the whole single responsibility thing, which I'm still learning, by the way, so be gentle). The idea is to create an event called OnMessageReceived and a public method called PostMessage that can only be called from code being executed by the factory. If the call is made from any other place then it would throw an InvalidOperationException to signify that the call was invalid. My first though to accomplish this is to use the call stack to my advantage:
using System.Diagnostics; // Needed for StackFrame
...
public static void PostMessage(string message) {
bool invalidCaller = true;
try {
Type callingType = new StackFrame(1).GetType();
if (callingType == typeof(DelegateFactory))
invalidCaller = false;
} catch { /* Gracefully ignore. */ }
if (invalidCaller)
throw new InvalidOperationException(...);
OnMessageReceived?.Invoke(null, new FactoryEventArgs(message));
}
However, I don't know for sure that this would prove to be reliable. The idea though is to allow the work to also send messages to the subscriber, but that may be a moot point because the object containing the work could just raise it's own OnMessageReceived event instead. I just don't like the idea of the exceptions being sent to the subscriber one way, and messages going out another. Maybe I'm just being picky? Starting to have a smell, the more I think on it.
EXAMPLE USE CASE
public class SomeObjectUsingTheFactory {
public bool TestConnection() {
DelegateFactory.DelegateWork((connectionString) => {
// Completely valid.
DelegateFactory.PostMessage("Attempting to establish a connection to SQL server.");
using (SqlConnection conn = new SqlConnection(connectionString))
conn.Open();
}, 3, "ABC123", out bool connectionMade);
// This should always throw an exception.
// DelegateFactory.PostMessage("This is a test.");
return connectionMade;
}
}
public class Program {
public static void Main(string[] args) {
DelegateFactory.OnMessageReceived += OnFactoryMessageReceived;
var objNeedingFactory = new SomeObjectUsingTheFactory();
if (objNeedingFactory.TestConnection())
Console.WriteLine("Connected.");
}
public static void OnFactoryMessageReceived(object sender, FactoryEventArgs e) {
Console.WriteLine(e.Data);
}
public static void OnFactoryExceptionOccurred(object sender, FactoryEventArgs e) {
string errorMessage = (e.Data as Exception).Message;
Console.WriteLine($"An error occurred. {errorMessage}");
}
}
In the example above, if we assume the connection continues to fail, the output should be:
Attempting to establish a connection to SQL server.
An error occurred. {errorMessage}
Attempting to establish a connection to SQL server.
An error occurred. {errorMessage}
Attempting to establish a connection to SQL server.
An error occurred. {errorMessage}
If it succeeds on the second attempt it should be:
Attempting to establish a connection to SQL server.
An error occurred. {errorMessage}
Attempting to establish a connection to SQL server.
Connected.
How can I ensure the method PostMessage is only called by code being executed by the factory?
NOTE: I'm not against changing the design if it's introducing bad practice. I'm completely open to new ideas.
COMPILER ERRORS: Also, any compilation errors in here are strictly oversights and typos. I manually typed this question up as I tried my best to work my way through the problem. If you encounter any issues, let me know and I'll fix them promptly.
You can do away with the stack-based security by introducing a context object that provides access to the event.
But first, a few notes. I'm not going to speak to the merits of this design because that's subjective. However, I will address some terminology, naming, and design matters.
.NET's naming convention for events does not includethe "On" prefix. Rather, the method that raises the event (marked private or protected virtual, depending on whether you can inherit the class) has the "On" prefix. I've followed this convention in the code below.
The name "DelegateFactory" sounds like something that create delegates. This does not. It accepts a delegate and you're using it to perform an action within a retry loop. I'm having a tough time word-smithing this one, though; I've called the class Retryer and the method Execute in the code below. Do with that what you will.
DelegateWork/Execute return a bool but you never check it. It's unclear if that's an oversight in the example consumer code or a flaw in this thing's design. I'll leave it to you to decide, but because it follows the Try pattern to determine if the output parameter is valid, I'm leaving it there and using it.
Because you're talking about network-related actions, consider writing one or more overloads that accept an awaitable delegate (i.e. returns Task<TOut>). Because you can't use ref or out parameters with async methods, you'll need to wrap the bool status value and the return value of the delegate in something, such as a custom class or a tuple. I will leave this as an exercise to the reader.
If an argument is null, make sure you throw ArgumentNullException and simply pass it the name of the argument (e.g. nameof(work)). Your code throws ArgumentException, which is less specific. Also, use the is keyword to ensure you're doing a reference equality test for null and not accidentally invoking overloaded equality operators. You'll see that in the code below, as well.
Introducing a Context Object
I'm going to use a partial class so that the context is clear in each snippet.
First, you have the events. Let's follow the .NET naming convention here because we want to introduce invoker methods. It's a static class (abstract and sealed) so those will be private. The reason for using invoker methods as a pattern is to make raising an event consistent. When a class can be inherited and an invoker method needs to be overridden, it has to call the base implemention to raise the event because the deriving class doesn't have access to the event's backing storage (that could be a field, as in this case, or perhaps the Events property in a Component-derived type where the key used on that collection is kept private). Although this class is uninheritable, it's nice to have a pattern you can stick to.
The concept of raising the event is going to go through a layer of semantic translation, since the code that registers the event handler may not be the same as the code that calls this method, and they could have different perspectives. The caller of this method wants to post a message. The event handler wants to know that a message has been received. Thus, posting a message (PostMessage) gets translated to notifying that a message has been received (OnMessageReceived).
public static partial class Retryer
{
public static event EventHandler<FactoryEventArgs> MessageReceived;
public static event EventHandler<FactoryEventArgs> ExceptionEncountered;
private static void OnMessageReceived(object sender, FactoryEventArgs e)
{
MessageReceived?.Invoke(sender, e);
}
private static void OnExceptionEncountered(object sender, FactoryEventArgs e)
{
ExceptionEncountered?.Invoke(sender, e);
}
}
Side note: You might want to consider defining a different EventArgs-derived class for ExceptionEncountered so you can pass the whole exception object for that event rather than whatever string data you cobble together from it.
Now, we need a context class. What will be exposed to the consumer is either an interface or an abstract base class. I've gone with an interface.
The semantic translation from "post a message" to "a message was received" is aided by the fact that FactoryEventArgs is unknown to the lambda that's posting the message. All it has to do is pass the message as a string.
public interface IRetryerContext
{
void PostMessage(string message);
}
static partial class Retryer
{
private sealed class RetryerContext : IRetryerContext
{
public void PostMessage(string message)
{
OnMessageReceived(this, new FactoryEventArgs(message));
}
}
}
The RetryerContext class is nested in the Retryer class (and private) for two reasons:
It needs access to at least one of the invoker methods that's private to the Retryer class.
Given the first point, it simplifies things by not exposing a nested class to the consumer.
Generally speaking, nested classes should be avoided, but this is one of those things that they're exactly designed to do.
Also note that the sender is this, i.e. the context object. The original implementation was passing work as the sender, which is not what's raising (sending) the event. Because it's a static method in a static class, there was no instance to pass before and passing null probably felt dirty; strictly speaking, the context is still not what's raising the event, but it's a better candidate than a delegate instance. It will also be passed as the sender when being used inside of Execute.
The implementation needs to be modified just slightly to include the context when invoking work. The work argument is now a Func<TIn, IRetryerContext, TOut>.
static partial class Retryer
{
public static bool Execute<TIn, TOut>(Func<TIn, IRetryerContext, TOut> work, int attemptThreshold, TIn input, out TOut output)
{
if (work is null)
throw new ArgumentNullException(nameof(work));
DelegationContext context = new DelegationContext();
for (int i = 0; i < attemptThreshold; i++)
{
try
{
OnMessageReceived(context, new FactoryEventArgs("Some message..."));
output = work(input, context);
return true;
}
catch (Exception e)
{
OnExceptionEncountered(context, new FactoryEventArgs(e.Message));
}
}
output = default;
return false;
}
}
OnMessageReceived is called from two different places: Execute and PostMessage, so if you ever need to change how the event is raised (maybe some add logging), it only needs to be changed in one place.
At this point, the problem of preventing unwanted message posting is solved because:
The event can't be raised arbitrarily since anything that calls it is private to the class.
A message can only be posted by something that has been given the ability to do so.
Small nit-pick: Yes, the caller could capture a local variable and assign the context to the outer scope, but then someone could also use reflection to find the event delegate's backing field and invoke it whenever they want, too. There's only so much you can reasonably do.
Finally, the consumer code needs to include the context in the lambda's parameters.
Here's your example use case, modified to use the implementation above. The lambda returns a string, the connection's current database, as the result of the operation. That's distinct and separate from the true/false returned to indicate whether it was a success after attemptThreshold attempts, which is now what's assigned to connectionMade.
public class SomeObjectUsingTheFactory
{
public bool TestConnection(out string currentDatabase)
{
bool connectionMade = Retryer.Execute((connectionString, context) =>
{
// Completely valid.
context.PostMessage("Attempting to establish a connection to SQL server.");
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
return conn.Database;
}
}, 3, "ABC123", out currentDatabase);
// Can't call context.PostMessage here because 'context' doesn't exist.
return connectionMade;
}
}
public class Program
{
public static void Main(string[] args)
{
Retryer.MessageReceived += OnFactoryMessageReceived;
var objNeedingFactory = new SomeObjectUsingTheFactory();
if (objNeedingFactory.TestConnection(out string currentDatabase))
Console.WriteLine($"Connected to '{currentDatabase}'.");
}
public static void OnFactoryMessageReceived(object sender, FactoryEventArgs e)
{
Console.WriteLine(e.Data);
}
public static void OnFactoryExceptionOccurred(object sender, FactoryEventArgs e)
{
string errorMessage = (e.Data as Exception).Message;
Console.WriteLine($"An error occurred. {errorMessage}");
}
}
As further exercises, you could also implement other overloads. Here are some examples:
An overload for a lambda that doesn't need to call PostMessage and therefore doesn't need the context. This has the same type for the dowork parameter as your original implementation.
public static bool Execute<TIn, TOut>(Func<TIn, TOut> work, int attemptThreshold, TIn input, TOut output)
{
return Execute((arg, _ /*discard the context*/) => work(arg), attemptThreshold, input, out output);
}
Overloads for lambdas that don't need need to return a value in an output parameter, and therefore use Action delegates instead of Func delegates.
public static bool Execute<TIn>(Action<TIn, IRetryerContext> work, int attemptThreshold, TIn input)
{
// A similar implementation to what's shown above,
// but without having to assign an output parameter.
}
public static bool Execute<TIn>(Action<TIn> work, int attemptThreshold, TIn input)
{
return Execute((arg, _ /*discard the context*/) => work(arg), attemptThreshold, input);
}
We have the following construct in our codebase, used to ensure a particular resource is disposed of after use:
using (var disposableThing = DisposableThing.Begin())
{
// do something
disposableThing.Finish(); // must always be called
}
Here's an example of its usage:
List<int> ids;
using (var disposableThing = DisposableThing.Begin())
{
ids = disposableThing.GetSomeIds();
disposableThing.Finish();
}
DoSomethingElseWith(ids);
Since this pattern is so common, we wrote a method on DisposableThing to encapsulate it:
static void ExecuteWithFinish(Action<DisposableThing> action)
{
using (var disposableThing = Begin())
{
action(disposableThing);
disposableThing.Finish();
}
}
which allows us to rewrite the second sample as:
// #4
List<int> ids;
DisposableThing.ExecuteWithFinish(disposableThing =>
{
ids = disposableThing.GetSomeIds();
});
DoSomethingElseWith(ids); // compiler error "Use of unassigned local variable 'ids'"
But the compiler refuses to compile that code because it has no way to know that ids will always be assigned after ExecuteWithFinish has completed (or thrown an exception, which will prevent the execution of DoSomethingElseWith anyway).
I know I could add an overload of ExecuteWithFinish that returns values from a passed-in Func, which is ugly.
I know I could subclass DisposableThing and override its Dispose method to call Finish, which is a cleaner, neater, and faster way than constructing a delegate each time (this is probably what I'll end up doing).
But for my own edification and in the spirit of "what if", is it possible to inform or even trick the compiler into allowing the code in #4 as written?
edit: Yes, I know I could write List<int> ids = null; and circumvent this issue entirely, but (a) I'd prefer not to perform unnecessary assignments (b) I'd like to change the code as little as possible.
I would take a different approach here.
I'm going to make the assumption that for some reason you must have a Finish() method that must always be called before Dispose(), which must also always be called.
That may be a rash assumption, and it does rather beg the question: Why don't you put the functionality of Finish() into the Dispose()? However...
Firstly, create an interface to encapsulate a disposable thing with a Finish() method:
public interface IDisposableThingWithFinish : IDisposable
{
void Finish();
}
and change your DisposableThing class so that it implements IDisposableThingWithFinish.
Then you could write a disposable class that encapsulates calling Finish() and then Dispose() like so:
public sealed class DisposingFinisher : IDisposable
{
readonly IDisposableThingWithFinish _item;
public Disposing(IDisposableThingWithFinish item)
{
if (item == null)
throw new ArgumentNullException(nameof(item));
_item = item;
}
public void Dispose()
{
try
{
_item.Finish();
}
finally
{
_item.Dispose();
}
}
}
You would use Finisher like so:
using (var disposableThing = new DisposingFinisher(DisposableThing.Begin()))
{
// Do something.
}
A simple null-assignment will avoid the compiler warning as explained in the documentation of compiler error CS0165:
List<int> ids = null;
Consider this code.
public class Class1
{
public void ThisShouldNotCompileBecauseOrderWasVoilated()
{
Call2();
Call1();
}
public void ThisShouldCompileBecauseProperOrderIsPresent()
{
Call1();
Call2();
}
private void Call1()
{
// some code
}
private void Call2()
{
// some more code
}
}
What code (or attribute) should I add in Call1()/Call2() which ensures that compiler complains for 1st method and passes for 2nd method. There will be some rule list which compiler will have to refer if order is not correct. In this example the rule list can say "Call1 Call2", meaning call Call1() before Call2()
This is for C# language for .NET 4.0
Thanks!
There's nothing within normal C# that you can specify for this.
You may be able to use something like NDepend to detect this, but I'm not sure.
You can create your own attribute and mark your methods using it. Then create an FXCop rule. FXCop fully integrates with your build process, and as long as both calls are taking place within the same method, the rule should be fairly easy to flesh out.
the compiler can't enforce method call ordering, since in many cases it cannot determine statically what the call order is. For example:
public void whichOrder(boolean b)
{
if (b) call1();
if (!b) call2();
if (b) call2();
if (!b) call1();
}
If it's necessary that the methods are called in the correct order, you have a few choices:
document the call order, so that callers know what to do. This doesn't enforce the order, but at least makes coders aware of it.
add state to your object to remember which method was called last, and validate the current called method is allowed next. This enforces the method check at runtime.
Use a mock framework (e.g. Moq) to unit test your clients. This checks at build time that the order is correct.
Which approach you choose depends on how critical the correct ordering is, and the consequences of calling the methods in the wrong order.
An alternative is to rework your design so that method ordering doesn't become an issue. For example, wrap both methods up in a third, call3() that invokes call1() and call2() in the correct order. Or perhaps, have call2() invoke call1() if it has not already been executed, and have call1() check if it's already run, and return silently if it doesn't need to run. If clients invoke call2() then call1(), you still internally get the effect of call1() first (from call2()'s internal call to call1()) and the client's call to call1() results in a no op.
E.g.
public void call3()
{
call1();
call2();
}
or
public void call2()
{
call1();
// rest of call2's logic
}
private boolean call1Called = false;
pubic void call1()
{
if (!call1Called)
{
call1Called=true;
call1Impl();
}
}
This is not exactly what you are asking ... but you could introduce another class:
public class Another1
{
public Another2 Call1()
{
// some code
return new Another2();
// could pass 'this' to Another2 constructor so it has all state
}
}
public class Another2
{
public void Call2()
{
// some more code
}
}
Now, starting from an instance of Another1 you can only do obj.Call1().Call2() and never obj.Call2().Call1(). Better yet, this enforcement is in the IDE as you type. Take a look at 'fluent' patterns also.
I ran across a pattern in a codebase I'm working on today that initially seemed extremely clever, then later drove me insane, and now I'm wondering if there's a way to rescue the clever part while minimizing the insanity.
We have a bunch of objects that implement IContractObject, and a class InvariantChecker that looks like this:
internal class InvariantChecker : IDisposable
{
private IContractObject obj;
public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}
public void Dispose()
{
if (!obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}
internal class Foo : IContractObject
{
private int DoWork()
{
using (new InvariantChecker(this))
{
// do some stuff
}
// when the Dispose() method is called here, we'll throw if the work we
// did invalidated our state somehow
}
}
This is used to provide a relatively painless runtime validation of state consistency. I didn't write this, but it initially seemed like a pretty cool idea.
However, the problem arises if Foo.DoWork throws an exception. When the exception is thrown, it's likely that we're in an inconsistent state, which means that the InvariantChecker also throws, hiding the original exception. This may happen several times as the exception propagates up the call stack, with an InvariantChecker at each frame hiding the exception from the frame below. In order to diagnose the problem, I had to disable the throw in the InvariantChecker, and only then could I see the original exception.
This is obviously terrible. However, is there any way to rescue the cleverness of the original idea without getting the awful exception-hiding behavior?
I don't like the idea of overloading the meaning of using in this way. Why not have a static method which takes a delegate type instead? So you'd write:
InvariantChecker.Check(this, () =>
{
// do some stuff
});
Or even better, just make it an extension method:
this.CheckInvariantActions(() =>
{
// do some stuff
});
(Note that the "this" part is needed in order to get the C# compiler to look for extension methods that are applicable to this.) This also allows you to use a "normal" method to implement the action, if you want, and use a method group conversion to create a delegate for it. You might also want to allow it to return a value if you would sometimes want to return from the body.
Now CheckInvariantActions can use something like:
action();
if (!target.CheckInvariants())
{
throw new ContractViolatedException();
}
I would also suggest that CheckInvariants should probably throw the exception directly, rather than just returning bool - that way the exception can give information about which invariant was violated.
This is a horrid abuse of the using pattern. The using pattern is for disposing of unmanaged resources, not for "clever" tricks like this. I suggest just writing straight forward code.
If you really want to do this:
internal class InvariantChecker : IDisposable
{
private IContractObject obj;
public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}
public void Dispose()
{
if (Marshal.GetExceptionCode() != 0xCCCCCCCC && obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}
Instead of this:
using (new InvariantChecker(this)) {
// do some stuff
}
Just do this (assuming you don't return from do some stuff):
// do some stuff
this.EnforceInvariants();
If you need to return from do some stuff, I believe some refactoring is in order:
DoSomeStuff(); // returns void
this.EnforceInvariants();
...
var result = DoSomeStuff(); // returns non-void
this.EnforceInvariants();
return result;
It's simpler and you won't have the problems you were having before.
You just need a simple extension method:
public static class InvariantEnforcer {
public static void EnforceInvariants(this IContractObject obj) {
if (!obj.CheckInvariants()) {
throw new ContractViolatedException();
}
}
}
Add a property to the InvariantChecker class that allows you to suppress the check/throw.
internal class InvariantChecker : IDisposable
{
private IContractObject obj;
public InvariantChecker(IContractObject obj)
{
this.obj = obj;
}
public bool Suppress { get; set; }
public void Dispose()
{
if (!this.Suppress)
{
if (!obj.CheckInvariants())
{
throw new ContractViolatedException();
}
}
}
}
internal class Foo : IContractObject
{
private int DoWork()
{
using (var checker = new InvariantChecker(this))
{
try
{
// do some stuff
}
catch
{
checker.Suppress = true;
throw;
}
}
}
}
If you current problem is to get original exception - go to Debug -> Exceptions and check "thrown" for all CLR exceptions. It will break when exception is thrown and as result you'll see it first. You may need to also turn off tools->options->debug->"my code only" option if exceptions are throw from "not your code" from VS point of view.
What is needed to make this nice is a clean means of finding out whether an exception is pending when Dispose is called. Either Microsoft should provide a standardized means of finding out at any time what exception (if any) will be pending when the current try-finally block exits, or Microsoft should support an extended Dispose interface (perhaps DisposeEx, which would inherit Dispose) which would accept a pending-exception parameter.
I'm creating a class that will house election results. I have a results class that has a static method that will parse a file and return a results class with the results from the file.
I want to make sure that only the static method can modify the results, so i've been using the internal modifier (Precinct.InternalCandidates) (The prevents instances of my class outside of the dll from accessing the methods, right?).
Anyway, I need to expose the candidates as a read only list to the instantiated version of my class, but I'll obviously need to be able to add candidates during the population process. So, I've created another parameter in the Precinct Class called Precinct.Candidates that exposes a read only version of InternalCandidates
Here's how I'd envision it to work:
Results r = Results.ParseResultsFile("PathToFile.txt");
r.Candidates.Add(new Candidate) // Should error here
Console.WriteLine(r.Candidates[0].Name) // Should work
Here's what I have for my class stubs:
public class Results {
private List<Precinct> precincts = new List<Precinct>();
public ReadOnlyCollection<Precinct> Precincts {
get { return this.precincts.AsReadOnly(); }
}
public Results() {}
public static Results ParseResultsFile(string filePath) { ... }
}
public class Precinct {
internal List<Contest> InternalContests { get; set; }
public ReadOnlyCollection<Contest> Contests {
get { return this.InternalContests.AsReadOnly(); }
}
public Precinct {
this.InternalContests = new List<Contest>();
}
}
Is there a better way to accomplish this?
I'm afraid I have a little bit of bad news Rob... using Reflection, one can completely circumvent access modifiers. They help to protect a team from themselves, but are not suited to providing security.
You will need to ensure the physical security of the code and ensure that nobody can load your DLL into an app domain of their own creation.
UPDATE:
I stand corrected by myself. You can set an attribute that prevents reflection UNLESS THE CALLER HAS FULL TRUST (update from Leppie). See how.
You can prevent callers without full trust from accessing your private/internal methods and fields but a full trust caller cannot be prevented from using reflection.
Again. Cleaning up my old questions... I ended up just rolling my own Collection.
Worked out wonderfully..