How to pass through items with certain logic? - c#

I'm looking for a way to pass through items with certain logic. The most obvious answer probably would be to use .Select which is sort of works with most of the cases but I have a special case and the question can be actually rephrased as how to call a certain method after an item is consumed by all subscribers?
I was thinking about an extension looking like this PassThrough(this IObservable<TSource> obj, Action<TSource, IObserver<TResult>> selector) and I would use it in the following way
.PassThrough((source, observer) => {
if(source != null) {
using(var result = new Result(source)) {
observer.OnNext(result);
}
}
});
The most important part of this is calling .Dispose for the result object after the object is passed to OnNext in other words after it is consumed by subscribers. I didn't find such extension method. Could somebody give an example how to achieve it with existing Rx.NET API or how to create an extension which will do this, presuming it is possible?

What you are looking for is probably Observable.Create via an extension method. In your case it may look like the following:
public static IObservable<Result> PassThrough(this IObservable<TSource> obj, T source) {
return Observable.Create(observer => {
if(source != null) {
using(var result = new Result(source)) {
observer.OnNext(result);
observer.OnCompleted();
}
} else {
observer.OnError(Some Error);
...
}
})
}
Obviously depending on whether you want to keep the stream going, you would omit the OnCompleted() call.
See here for more information on usage of Observable.Create:
http://introtorx.com/Content/v1.0.10621.0/04_CreatingObservableSequences.html#CreationOfObservables

Related

C# best practice: "break" from within Action<> callback called in a loop?

I had to write my own foreach method for various reasons. This resembles an IEnumerable foreach statement:
public void ForEachEdge(in Vertex vertex, Action<Edge> callback)
{
var edge = GetEdge(vertex.BaseEdgeIndex);
do
{
callback.Invoke(edge);
edge = GetEdge(edge.GetNext(vertex.Index));
} while (edge.Index != vertex.BaseEdgeIndex);
}
I'm using it like so but I wish to be able to "break" out of the entire loop:
ForEachEdge(edge.Vertex0Index, (e) =>
{
if (inEdge.AreConnectingSameVertices(e))
{
// break out of inner while loop here ...
}
});
What would be best practice to break?
Return a status value?
Pass a "ref bool stopEnumerating" parameter in? (requires class instance to wrap it in, right?)
Your thoughts ...
I'm mostly concerned about what end users (developers) would expect in such a case.
the ref parameter method won't be as clean as a return value indicating continuation status. You would have to switch to a Func<Edge, bool>
Func<Edge, bool> callback;
...
if (callback.Invoke(edge)) {
/// do your break logic
}
I decided that (for now) I'll go with a Predicate<> rather than Action<>:
public void ForEachEdge(in Vertex vertex, Predicate<Edge> callback)
{
var edge = GetEdge(vertex.BaseEdgeIndex);
do
{
if (callback.Invoke(edge))
break;
edge = GetEdge(edge.GetNextRadialEdgeIndex(vertex.Index));
} while (edge.IsValid && edge.Index != vertex.BaseEdgeIndex);
}
Which makes the user's code look like this:
ForEachEdge(edge.Vertex0Index, e =>
{
if (inEdge.AreConnectingSameVertices(e))
{
// found it, do something, then exit loop
return true;
}
// continue with next item
return false;
});
The nicest thing about this solution: both Predicate<> and Action<> variants can exist side-by-side! User either returns true/false from the predicate, or does not return anything and thus uses the Action<> version, like so:
ForEachEdge(edge.Vertex0Index, e =>
{
if (inEdge.AreConnectingSameVertices(e))
{
// do stuff
}
});
Purrfect! :)

In Azure API for VM, is there a way to define many existing data disks with one method?

I have a block of fluent C# code:
If I knew how many disks existed the syntax would be:
var tempVM = await azure.VirtualMachines.Define(targetVMName)
.WithRegion(vm.Region)
.WithExistingResourceGroup(targetResourceGroupName)
.WithNewPrimaryNetworkInterface(nicDefinitions[0])
.WithSpecializedOSDisk(disks[0], disks[0].OSType.Value)
.WithSize(vm.Size)
.WithTags(tags)
.WithExistingDataDisk(d[0]) <<<<<<<
.WithExistingDataDisk(d[1]) <<<<<<<
.WithExistingDataDisk(d[2]) <<<<<<<
.WithExistingDataDisk(d[3]) <<<<<<<
.CreateAsync();
I may have 0 or more datadisks to add. Is there a fluent syntax to support 0 or more disks ?
Assuming this is using extension method on an interface named IWithManagedCreate, you have this method:
public static IWithManagedCreate WithExistingDataDisk(this IWithManagedCreate vm, IDisk disk)
{
// ...
return vm;
}
You could simply add an extension method of your own with a params IDisk[] overload:
public static IWithManagedCreate WithExistingDataDisks(this IWithManagedCreate vm, params IDisk[] disks)
{
foreach (var disk in disks)
{
vm = vm.WithExistingDataDisk(disk);
}
return vm;
}
And call it like that:
.WithTags(tags)
.WithExistingDataDisks(d) // passing the array containing 0 or more disks
.CreateAsync();
So, to answer the question, no, fluent syntax is nothing special, just a chain of method calls. When you chain method calls (by letting each method return something that you can call more methods on), you can't make them conditional; you can make a method however do nothing as demonstrated above. When you call it with an empty array, nothing happens.
The WithExistingDataDisk is declared in the IWithManagedDataDisk interface.
This interface doesn't provide any method to add many existing IDisk in one call.
Anyway, you can implement it as an extension method like this :
public static class WithManagedDataDiskExtensions
{
// allow to manually specify many disks to add
public static IWithManagedDataDisk WithExistingDataDisks(this IWithManagedDataDisk self, params IDisk[] disks)
{
return self.WithExistingDataDisks((IEnumerable<IDisk>) disks);
}
// allow to add an enumerable of many disks
public static IWithManagedDataDisk WithExistingDataDisks(this IWithManagedDataDisk self, IEnumerable<IDisk> disks)
{
foreach (var disk in disks)
self = self.WithExistingDataDisk(disk);
return self;
}
}
and use it like that:
var tempVM = await azure.VirtualMachines.Define(targetVMName)
.WithRegion(vm.Region)
.WithExistingResourceGroup(targetResourceGroupName)
.WithNewPrimaryNetworkInterface(nicDefinitions[0])
.WithSpecializedOSDisk(disks[0], disks[0].OSType.Value)
.WithSize(vm.Size)
.WithTags(tags)
.WithExistingDataDisks(d[0], d[1], d[2], d[3])
//.WithExistingDataDisks(d)
.CreateAsync();
Often in fluent API's you can use an assignment in a loop, like this:
var expTempVM = azure.VirtualMachines.Define(targetVMName)
.WithRegion(vm.Region)
.WithExistingResourceGroup(targetResourceGroupName)
.WithNewPrimaryNetworkInterface(nicDefinitions[0])
.WithSpecializedOSDisk(disks[0], disks[0].OSType.Value)
.WithSize(vm.Size)
.WithTags(tags);
foreach (var d in disks)
{
expTempVM = expTempVM.WithExistingDataDisk(d);
}
var tempVM = await expTempVM.CreateAsync();
As the basic design of a fluent API is that each method returns the same type that it operates on.
And if you can do that, you can also define your own extension method, .WithExistingDataDisks or similar.

"yield return" from event handler

I have a class which takes a stream in the constructor. You can then set up callbacks for various events, and then call StartProcessing. The issue is that I want to use it from a function which should return an IEnumerable.
Example:
public class Parser
{
public Parser(System.IO.Stream s) { // saves stream and does some set up }
public delegate void OnParsedHandler(List<string> token);
public event OnParsedHandler OnParsedData;
public void StartProcessing()
{
// reads stream and makes callback when it has a whole record
}
}
public class Application
{
public IEnumerable<Thing> GetThings(System.IO.Stream s)
{
Parser p = new Parser(s);
p.OnParsedData += (List<string> str) =>
{
Thing t = new Thing(str[0]);
// here is where I would like to yield
// but I can't
yield return t;
};
p.StartProcessing();
}
}
Right now my solution, which isn't so great, is to put them all the Things into a List which is captured by the lambda, and then iterate over them after calling StartProcessing.
public class Application
{
public IEnumerable<Thing> GetThings(System.IO.Stream s)
{
Parser p = new Parser(s);
List<Thing> thingList = new List<Thing>();
p.OnParsedData += (List<string> str) =>
{
Thing t = new Thing(str[0]);
thingList .Add(t);
};
p.StartProcessing();
foreach(Thing t in thingList )
{
yield return t;
}
}
}
The issue here is that now I have to save all of the Thing objects into list.
The problem you have here is that you don't fundamentally have a "pull" mechanic here, you're trying to push data from the parser. If the parser is going to push data to you, rather than letting the caller pull the data, then GetThings should return an IObservable, rather than an IEnumerable, so the caller can consume the data when it's ready.
If it really is important to have a pull mechanic here then Parser shouldn't fire an event to indicate that it has new data, but rather the caller should be able to ask it for new data and have it get it; it should either return all of the parsed data, or itself return an IEnumerable.
Interesting question. I would like to build upon what #servy has said regarding push and pull. In your implementation above, you are effectively adapting a push mechanism to a pull interface.
Now, first things first. You have not specified whether the call to the StartProcessing() method is a blocking call or not. A couple of remarks regarding that:
If the method is blocking (synchronous), then there is really no point in adapting it to a pull model anyway. The caller will see all the data processed in a single blocking call.
In that regard, receiving the data indirectly via an event handler scatters into two seemingly unrelated constructs what should otherwise be a single, cohesive, explicit operation. For example:
void ProcessAll(Action<Thing> callback);
On the other hand, if the StartProcessing() method actually spawns a new thread (maybe better named BeginProcessing() and follow the Event-based Asynchronous Pattern or another async processing pattern), you could adapt it to a pull machanism by means of a synchronization construct using a wait handle: ManualResetEvent, mutex and the like. Pseudo-code:
public IEnumerable<Thing> GetThings(System.IO.Stream s)
{
var parser = new Parser(s);
var waitable = new AutoResetEvent(false);
Thing item = null;
parser.OnParsedData += (Thing thing) =>
{
item = thing;
waitable.Set();
};
IAsyncResult result = parser.BeginProcessing();
while (!result.IsCompleted)
{
waitable.WaitOne();
yield return item;
}
}
Disclaimer
The above code serves only as a means for presenting an idea. It is not thread-safe and the synchronization mechanics do not work properly. See the producer-consumer pattern for more information.

method queue delegate comparisons

I have a Queue that holds a list of delegates that correspond to methods that I want to run in the future. I would like to only have singular instances of any particular method/parameter in queue. In other words, a queue of DoOne(), DoTwo(2), DoThree(3) should be possible where as a queue of DoOne(), DoTwo(2), DoTwo(2) should not be allowed.
I have noticed that _queue.Contains(Func< int >) works through the minimal testing that I have done, but I am worried if I am missing something. Is this a sufficient enough test to determine whether a particular method/parameter is queued, to satisfy what I am trying to accomplish?
Queue<Func<int>> _queue = new Queue<Func<int>>();
void Queue(Func<int> Method)
{
if (!_queue.Contains(Method))
_queue.Enqueue(Method);
}
void QueueOne()
{
Queue( () => DoOne() );
}
void QueueTwo(int val)
{
Queue( () => DoTwo(val) );
}
void DoOne()
{
return 1;
}
void DoTwo(int val)
{
return val;
}
Since each time you call QueueOne or QueueTwo, you create a new function that is passed to the Queue function, I have my doubts that you can find a way to compare those to each other and determine that they match.
This leads me to recommend that you pass an identifier that you will use to make the uniqueness comparison.
In my sample code below, I chose to do this using the CallerMemberName to identify the name of the calling function (i.e. "QueueOne" or "QueueTwo") and refuse to enqueue the item if the queue still had a matching entry.
Queue<Tuple<string, Func<int>>> _queue = new Queue<Tuple<string, Func<int>>>();
void Queue(Func<int> method, [CallerMemberName] string caller = null)
{
if (!_queue.Any(v => v.Item1 == caller))
_queue.Enqueue(Tuple.Create(caller, method));
}
void QueueOne()
{
Queue(() => DoOne());
}
void QueueTwo(int val)
{
Queue(() => DoTwo(val));
}
int DoOne()
{
return 1;
}
int DoTwo(int val)
{
return val;
}
Since you are calling with a parameter they are treated different objects (see Closures in c#)
Change your logicto check the duplication to:
if (!_queue.Where(x => x.Method == Method.Method).Any())
_queue.Enqueue(m);
this will help you to stop adding same method again (even if they have diff parameters)

Using Delegate to execute code at the method entry and exit

I have code that does very repetitive things such as logging the method entry and exit. In between, I execute some business logic. Is there a way I could handle that with a Delegate?
Here is what I have so far. However, it is really restrictive due to the func parameters I must passing. Anybody has a better idea?
Func<Func<int>, int> logAction = new Func<Func<int>, int>(func =>
{
try
{
Console.WriteLine("Logging...");
return func();
}
finally
{
Console.WriteLine("End Logging...");
}
});
Postsharp is perfect for this- it is an Aspect Orientated Programming library that features compile time weaving, so it wont impact on performance like run time weaving. This probably doesn't explain much if your new to AOP but basically, it will allow you to declare logging on a method like this:
<Logging> //apply an aspect that will log entrance/exit of method
void MyMethod(params)
{
//do something that might throw an exception (or not)
}
For an example (and source code) on using postsharp for logging, see http://www.sharpcrafters.com/solutions/logging
It seems that one of the AOP frameworks could solve your issue.
private void LogAction(string title, Action action)
{
Logger.Write(string.Format("Entering %0", title));
action();
Logger.Write(string.Format("Leaving %0", title));
}
Sample usage with no return value:
LogAction("DoSomething", () => DoSomething());
Sample usage with return value:
int intResult = 0;
LogAction("Square", () => intResult = Square(4, 4));
The easiest way to do this is to wrap everything inside of an Action and then just execute that in a method
public void log(Action methodToExecute)
{
try
{
Console.WriteLine("Logging...");
methodToExecute();
}
finally
{
Console.WriteLine("End Logging...");
}
}
Then call it creating a generic action for your function
//no return
log(() => yourFunciton(optionalParmeters));
//return to something
log(() => someVar = yourFunction(optionalParameters));

Categories

Resources