Need help to understand Moq better - c#

I've been looking at the Moq documentation and the comments are too short for me to understand each of things it can do.
The first thing I don't get is It.IsAny<string>(). //example using string
Is there an advantage of using this over just putting some value in? I know people say to use this if you don't care about the value, but if you don't care about the value can't you just do "a" or something? This just seems like more typing.
Secondly, when would be an example be of when you would not care about the value? I thought Moq needs the value to match up stuff.
I don't get what It.Is<> is for at all or how to use it. I don't understand the example and what it is trying to show.
Next, I don't get when to use Times (and its AtMost methods and similar). Why would you limit the number of times something is set up? I have some AppConfig value that I need to use twice. Why would I want to limit it to, say, once? This would just make the test fail. Is this to stop other people from adding another one to your code or something?
I don't get how to use mock.SetupAllProperties();
What does it set up the properties with?
I don't also get why there are so many different ways to set up a property and what their differences are. The documentation has:
SetupGet(of property)
SetupGet<TProperty>
I noticed that a lot of the stuff in Moq shows () and <> - what's the difference between them and what would they look like in use?
I also don't get why they have SetupGet. Would you not use SetupSet to set a property?
SetupSet has five different ways to use it in the documentation. Plus another one called SetupProperty. So I don't understand why there are so many.
On a side note, I am wondering if variables used in lambdas are independent of other lambdas. E.g.:
mock.setup(m => m.Test);
stop.setup(m => m.Test);
Would this be ok or would there be some conflict between the variable m?
Finally, I was watching this video and I am wondering if it shows Visual Studio. His Intellisense looks different. A lightbulb pops up for him (I am happy mine does not, as it brings back painful memories of netbeans), and there are lines going from one opening brace to the closing brace and etc.

It.IsAny / It.Is
These can be useful when you're passing a new reference type within the code under test. For instance, if you had a method along the lines of:
public void CreatePerson(string name, int age) {
Person person = new Person(name, age);
_personRepository.Add(person);
}
You might want to check the add method has been called on the repository,
[Test]
public void Create_Person_Calls_Add_On_Repository () {
Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
PersonManager manager = new PersonManager(mockRepository.Object);
manager.CreatePerson("Bob", 12);
mockRepository.Verify(p => p.Add(It.IsAny<Person>()));
}
If you wanted to make this test more explicit you can use It.Is by supplying a predicate the person object must match,
[Test]
public void Create_Person_Calls_Add_On_Repository () {
Mock<IPersonRepository> mockRepository = new Mock<IPersonRepository>();
PersonManager manager = new PersonManager(mockRepository.Object);
manager.CreatePerson("Bob", 12);
mockRepository.Verify(pr => pr.Add(It.Is<Person>(p => p.Age == 12)));
}
This way the test will through an exception if the person object that was used to call the add method didn't have the age property set to 12.
Times
If you had a method along the lines of:-
public void PayPensionContribution(Person person) {
if (person.Age > 65 || person.Age < 18) return;
//Do some complex logic
_pensionService.Pay(500M);
}
One of the things that you might want to test is that the pay method does not get called when a person aged over 65 is passed into the method
[Test]
public void Someone_over_65_does_not_pay_a_pension_contribution() {
Mock<IPensionService> mockPensionService = new Mock<IPensionService>();
Person p = new Person("test", 66);
PensionCalculator calc = new PensionCalculator(mockPensionService.Object);
calc.PayPensionContribution(p);
mockPensionService.Verify(ps => ps.Pay(It.IsAny<decimal>()), Times.Never());
}
Similarly, it's possible to imagine situations where you're iterating over a collection and calling a method for each item in the collection and you'd like to make sure that it's been called a certain amount of times, other times you simply don't care.
SetupGet / SetupSet
What you need to be aware of with these guys is that they reflect how your code is interacting with the mock rather than how you're setting up the mock
public static void SetAuditProperties(IAuditable auditable) {
auditable.ModifiedBy = Thread.CurrentPrincipal.Identity.Name;
}
In this case, the code is setting the ModifiedBy property of the IAuditable instance while it's getting the Name property of the current instance of IPrincipal,
[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
Mock<IAuditable> mockAuditable = new Mock<IAuditable>();
mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");
Thread.CurrentPrincipal = mockPrincipal.Object;
AuditManager.SetAuditProperties(mockAuditable.Object);
mockPrincipal.VerifyGet(p => p.Identity.Name);
mockAuditable.VerifySet(a => a.ModifiedBy = "test");
}
In this case, we're setting up the name property on the mock of IPrincipal so it returns "test" when the getter is called on the Name property of Identity we're not setting the property itself.
SetupProperty / SetupAllProperties
Looking at the test above if it was changed to read
[Test]
public void Accesses_Name_Of_Current_Principal_When_Setting_ModifiedBy() {
Mock<IPrincipal> mockPrincipal = new Mock<IPrincipal>();
Mock<IAuditable> mockAuditable = new Mock<IAuditable>();
mockPrincipal.SetupGet(p => p.Identity.Name).Returns("test");
var auditable = mockAuditable.Object;
Thread.CurrentPrincipal = mockPrincipal.Object;
AuditManager.SetAuditProperties(auditable);
Assert.AreEqual("test", auditable.ModifiedBy);
}
The test would fail. This is because the proxy created by Moq doesn't actually do anything in the set method of a property unless you tell it to. In effect, the mock object looks a bit like this
public class AuditableMock : IAuditable {
public string ModifiedBy { get { return null; } set { } }
}
To get the test to pass you have to tell Moq to set up the property to have the standard property behavior. You can do this by calling SetupProperty and the mock will look more like
public class AuditableMock : IAuditable {
public string ModifiedBy { get; set; }
}
and the test above would pass as the value "test" would now get stored against the mock. When mocking complex objects you might want to do this for all properties, hence the SetupAllProperties shortcut
Finally, the lightbulb in the IDE is the ReSharper plugin.

If you don't care about the exact value of a property, it's far better to use .IsAny because you are being explicit about the fact that the exact value is not important. If you hardcode it as "abc", then it is not clear if your code you are testing depends on starting with "a" or ending with "c" or being 3 chars long, etc. etc.

Related

Why is my CollectionAssert in my Unit Test always failing in my .NET Application?

I'm writing a unit test which needs to check if two arrays of object match each other. I've tried a few different approaches but all of them fail. The most obvious approach was the CollectionAssert which, according to what I have read, doesn't care about the source only the values and order of the data itself, despite the two array of objects matching each other, the test still fails and I'm lost as to why.
Let's take my unit test
[TestMethod]
public async Task GetMyData_ShouldReturnDataDto_WhenAllIsOk()
{
// Arrange
var userId = "123-456";
Shared.Car customer = new()
{
Id = userId,
OwnerProfile = new Shared.OwnerProfile
{
Title = "Mr",
FirstName = "Bob",
Surname = "Smith",
CarsOwned = new Shared.CarsOwned[]
{
new CarsOwned {
Make = "Ford",
Model = "Mustang",
Rental = false
},
new CarsOwned {
Make = "Ford",
Model = "Fiesta",
Rental = true
}
}
}
};
customerRepo.GetCustomerById(Arg.Any<string>()).Returns(customer);
// Act
var data = await sut.GetCustomerProfile(userId);
// Assert
CollectionAssert.AreEqual(customer.OwnerProfile.CarsOwned, data.CarsOwned);
}
When I set a break point in my test to debug it, I can clearly see that both instances of CarsOwned in the CollectionAssert have identidcal data in the identical order although the sources are different.
Is the CollectionAssert the most appropriate for this setup? I believed it was based on the documentation and the described behaviour.
When I run the test I recieve the error of:
CollectionAssert.AreEqual failed. (Element at index 0 do not match.)
This suggest to me that it's not happy that it's comparing the two arrays from different sources but I could be wrong about that. Any help is appreciated.
I think the issue is that you did not override the Equals() method in the CarsOwned class. I assume that it is this method which is used by CollectionAssert.AreEqual.
By default, the Equals() method return true only if the both parameters have the same reference (~the memory address). It means that in your mind both objects are equals, but for the computer they are completely different objects. So you have to tell to the program how to compare two instance of the same class.
I let you search how implement a correct and efficient Equals() method, but this is not very complicate (because you do not have a lot of field and there is not some complex business logic).
See you, Dylan

How do I get NSubstitute mocks to fail when the arguments don't match the given pattern?

I'm responsible for the testing of a legacy software developed in C and C# that my team is maintaining. The original team used NSubstitute 3.1 to create test doubles for delegates in order to perform unit test of the APIs for the C# sections. Here's one such test double, where irrelevant details have been omitted:
private static byte[] MockSelectByAidWithoutData(ushort retVal)
{
var expectedIn= "FFFEFDFCFB".HexToBytes();
var expectedOut= "010203040506070809".HexToBytes();
var fake = Substitute.For<SomeDelegate>();
fake(Arg.Is<byte[]>(x => expectedIn.SequenceEqual(x.Take(expectedIn.Length))),
Arg.Is(0x00),
Arg.Is(expectedIn.Length),
Arg.Any<int>(),
Arg.Any<int>(),
out int outputLength)
.Returns(x =>
{
expectedOut.CopyTo((Array)x[0], 0);
x[5] = expectedOut.Length;
return retVal;
}
);
Mediator.GetInstance().Delegate = fake;
return expectedOut;
}
Now, if the fake delegate is invoked with arguments that match what is specified in the fake() call, it returns the retVal value and everybody is happy. However, if some value won't match, it returns zero. Since zero is a valid but incorrect value, the execution continues and I get an error that is not the root cause of the issue I am testing (i.e. bad output when the problem is actually bad input)
I am looking for a way to either:
specify a "catch all" behaviour for the values that won't match the expectations, or
get an exception if the arguments don't match the expectation
so that the test case would fail immediately upon reception of the wrong input with a meaningful message and without triggering further behaviour that would just pollute the outcome of the test.
Thanks in advance,
DeK
P.S. I can probably switch safely to a more recent version of NSubstitute if that's really necessary.
specify a "catch all" behaviour for the values that won't match the expectations
I think I've found a way you can do this. If you first stub the "catch all" / failure case for all arguments, you can then stub more specific calls. NSubstitute will try to match the most recent specifications provided, falling back to earlier stubbed values.
Here is a sample.
Note it is using Configure from NSubstitute.Extensions namespace introduced in NSubstitute 4.x. This isn't strictly necessary because NSubstitute will automatically assume you are configuring a call if you are using argument matchers, but it is a good pattern to use when configuring overlapping calls like this.
using NSubstitute;
using NSubstitute.Extensions; // required for Configure()
public class Thing {
public string Id { get; set; }
}
public interface ISample {
int Example(Thing a, string b);
}
public class UnexpectedCallException : Exception { }
[Fact]
public void ExampleOfStubOneCallButFailOthers() {
var sub = Substitute.For<ISample>();
// Catch all case:
sub.Example(null, null).ReturnsForAnyArgs(x => throw new UnexpectedCallException());
// Specific case. We use Configure from NSubstitute.Extensions to
// be able to stub this without getting an UnexpectedCallException.
// Not strictly necessary here as we're using argument matchers so NSub
// already knows we're configuring a call, but it's a good habit to get into.
// See: https://nsubstitute.github.io/help/configure/
sub.Configure()
.Example(Arg.Is<Thing>(x => x.Id == "abc"), Arg.Any<string>())
.Returns(x => 42);
// Example of non-matching call:
Assert.Throws<UnexpectedCallException>(() =>
sub.Example(new Thing { Id = "def" }, "hi")
);
// Example of matching call:
Assert.Equal(42, sub.Example(new Thing { Id = "abc" }, "hello"));
}
You could extend this to include information about arguments that do not match, but that will be a bit of custom work. If you look at some of NSubstitute's argument formatting code that might be re-usable to help with this.
Update to include delegate example
I just ran this with a delegate instead and it also passes:
public delegate int SomeDelegate(Thing a, string b);
[Fact]
public void ExampleOfStubOneDelegateCallButFailOthers() {
var sub = Substitute.For<SomeDelegate>();
sub(null, null).ReturnsForAnyArgs(x => throw new UnexpectedCallException());
sub.Configure()
.Invoke(Arg.Is<Thing>(x => x.Id == "abc"), Arg.Any<string>())
.Returns(x => 42);
Assert.Throws<UnexpectedCallException>(() => sub(new Thing { Id = "def" }, "hi"));
Assert.Equal(42, sub(new Thing { Id = "abc" }, "hello"));
}

Moq Setup override

I have gone through all the previous answers and none of them solve my problem.
lets say that i have the following code:
public interface ISomeInterface
{
int SomeMethod(int a, string b);
}
Now i have a common mocking class that defines some default behaviour for the above method
public class CommonMock
{
public Mock<ISomeInterface> MockInterface = new Mock<ISomeInterface>().Setup(x => x.SomeMethod(It.IsAny<int>(), It.IsAny<string>())).Returns(It.IsAny<int>());
}
I need some default behaviour because I have a whole lot of test cases which need a default behaviour.
But in some specific test scenarios, in a totally separate test class, i need to be able to return a different value as i am testing some specific test case.
Something like below:
[Test]
public void TestSomeMethodSpecific()
{
var commonMock = new CommonMock();
commonMock.MockInterface.Setup(x => x.SomeMethod(It.IsAny<int>(), It.IsAny<string>())).Returns(42);
// Do some test based on the new return value
}
How can I achieve that?
Below i am attaching a bit of the actual code:
Common Setup
public class MockStore
{
public Mock<IProcessHandler> ProcessHandler = new Mock<IProcessHandler>();
ProcessHandler.Setup(x => x.GetCurrentProcessRunId()).Returns(It.IsAny<int>());
}
Overridden Setup in a test class
var mockstore = new MockStore();
mockStore.ProcessHandler.Setup(x => x.GetCurrentProcessRunId()).Returns(25);
And there are almost 50 to 70 such mocks each of which return from simple types to complex classes.
That should work? If you create a subsequent setup on a method and it's non-conditional (no constraints on the arguments) then it removes all previous setups for the method.
You can see my answer here that explains it with the source code.
If you want multiple Setups that are conditional, to return different values based on the arguments, then see How to setup a method twice for different parameters with mock.
Without seeing your full code, perhaps you are already using conditional Setups. In which case the order is important and perhaps you are overriding an earlier Setup with a more general one.
You could have global mock objects that you modify as you go. For instance I have this:
[TestClass]
public class StoreServiceTest
{
Mock<IAccess> mockAccess;
Mock<IAccess> mockAccessNoData;
Mock<IDataReader> mockReader;
Mock<IDataReader> mockReaderNoData;
Mock<IStoreService> mockStoreService;
And then on the TestInitiailize, I Setup the default implementation as follows:
mockReader = new Mock<IDataReader>();
mockReader.Setup(m => m.IsDBNull(It.IsAny<int>())).Returns(false);
mockReader.Setup(m => m.GetString(It.IsAny<int>())).Returns("stub");
mockReader.Setup(m => m.GetBoolean(It.IsAny<int>())).Returns(true);
mockReader.Setup(m => m.GetInt32(It.IsAny<int>())).Returns(32);
mockReader.SetupSequence(m => m.Read()).Returns(true).Returns(false); // setup sequence to avoid infinite loop
mockAccess = new Mock<IAccess>();
mockAccess.Setup(m => m.ReadData(It.IsAny<string>(), It.IsAny<object[]>())).Returns(mockReader.Object);
mockReaderNoData = new Mock<IDataReader>();
mockReaderNoData.Setup(m => m.Read()).Returns(false);
mockAccessNoData = new Mock<IAccess>();
mockAccessNoData.Setup(m => m.ReadData(It.IsAny<string>(), It.IsAny<object[]>())).Returns(mockReaderNoData.Object);
mockStoreService = new Mock<IStoreService>();
And now for a default kind of test, all I do is pass the mockReader.Object which should have the default implementation since every test begins with TestInitialize, and then for a special case, say I want to return "sub" instead of "stub" for IDataReader's GetString() method, I can do something like this:
mockReader.Setup(m => m.GetString(It.IsAny<int>())).Returns((int col) => {
if (col == 2) return "sub";
else return "stub";
});
Hope that helps!

How to Mock with Moq to do foreach row in table

I'm a C# and Moq newb. I have some code that looks like the following and I want to unit test it, using Moq.
Data.Foo.FooDataTable tbl = Adapter.GetFooByID(id);
foreach (Data.Foo.FooRow row in tbl)
{
x = row.bar
...
}
How do I set up the mocks? Current broken attempt:
var adapter = new Mock<FooTableAdapter>();
var table = new Mock<Foo.FooDataTable>();
var rows = new Mock<DataRowCollection>();
var row = new Mock<Foo.FooRow>();
rows.Setup(x => x.GetEnumerator().Current).Returns(row.Object);
table.Setup(x => x.Rows).Returns(rows.Object);
adapter.Setup(x => x.GetFooByID(1)).Returns(table.Object);
_adapter = adapter.Object;
If I don't try to add the row, I get a NullReferenceException in the foreach. If I do try to add the row, I get a System.NotSupportedException: Type to mock must be an interface or an abstract or non-sealed class.
Mocks are awesome and all but they really are testing tools of last resort -- what you reach for when you've got some impossible to create object you can't avoid depending on -- such as HttpContext.
In this case, you probably don't want to create a moq mock of the DataTable -- you can just new up one with appropriate data. What you'd want to moq mock would be the call to Adapter.GetFooById() to spit back your test double of a data table.
Mocks should only be used to create fake dependencies when you want to test the behaviour of something that requires said dependency, but you don't want (or can't) actually create a "real" instance of that dependency. Any test method with more than a couple of mocks is headed in the wrong direction because it's a sign that you have either too many dependencies, or that you are testing too many unrelated things.
In the code you have above, there are no dependencies, so Mocks wouldn't be appropriate really what you need.
You really need to think about what exactly it is you are trying to test here. For the sake of argument let's assume that the code you showed is from a method:
public class MyFooClass
{
public int DoFooFooData(FooAdapter Foo)
{
Data.Foo.FooDataTable tbl = Adapter.GetFooByID(id);
//just imagining what you might do here.
int total=0;
foreach (Data.Foo.FooRow row in tbl)
{
x = row.bar
//just imagining what you might do here.
total+=x;
}
return total;
}
}
Now, let's further suppose that you want to unit test this method. In this case in order to call the method you have to supply a working FooAdapter instance because the method depends on it in order to work
But let's now say that you are not currently in possession of a FooAdapter because it doesn't exist, or maybe you can't supply one because FooAdapter makes a database connection which is a no-no in unit testing.
What we need to do in order to test DoFooFooData is to supply a fake (Mock) FooAdapter, which only implements the GetFooByID method, in order for your function to execute.
To do this you'll have to either make FooAdapter abstract or (I recommend) declare it by interface:
public interface IFooAdapter
{
Data.Foo.FooDataTable GetByID(int id);
}
(later on you'll need to change FooAdapter class to implement IFooAdapter if you want to actually use it with the DoFooFooData method for real)
Now change your method signature:
public void DoFooFooData(IFooAdapter Foo)
{
Data.Foo.FooDataTable tbl = Adapter.GetFooByID(id);
int total=0;
foreach (Data.Foo.FooRow row in tbl)
{
x = row.bar
//just imagining what you might do here
total+=x;
}
return total;
}
And finally in your test method, you can mock this dependency:
void DoFooFooData_DoesSomeFooAndReturns3()
{
var mock = new Mock<IFooAdapter>();
var table = new Data.Foo.FooDataTable();
table.Add(new Data.Foo.FowRow{bar=1});
table.Add(new Data.Foo.FowRow{bar=2});
mock.Setup(m=>m.GetByID(It.IsAny<int>()).Returns(table);
var sut = new MyFooClass();
var expected=3;
var actual=sut.DoFooFooData(mock.Object);
Assert.AreEqual(expected,actual);
}
Of course if you need to Mock FooDataTable as well you can follow the same pattern as you did with the IFooAdapter but you need to stop at this point and ask yourself if you shouldn't be creating a separate test in which you Mock an IFooDataTable and ensure that it does what it's supposed to do (Add method or whatever) and so on...at the point when you were sure that the behavioural contract of IFooDataTable is OK, you'd then implement it as a concrete "stub" which you can then use in place of any FooDataTable references in the context of an IFooAdapter...but now you're into integration tests which is a story for another day...

Evaluating a set of rules defined in a string

I made a system that creates a simple string with Function/Response format, example:
Check('Value'):ShowImage(#)|Check('Value'):OtherFunction(#)....and so on
Where Check is the name of a function, Value is the parameter, ShowImage is the name of a Response function, # is the entry paremeter (result of the previous function). The pipe splits another Function/Response pair that fires if the first Check('Value') function once "checked" were not satisfied (say, if the parameter was not accomplished the Check condition the function is invalid and hence the Response part in the first Function/Response pair is not executed, so system keep trying Functions awaiting to find the one that executes the right Response).
The way the application should work is to evaluate each rule (similar to a JavaScript eval function) and take appropriate action based on function results.
At first glance, it looks complicated, because first of all I need to cast the string to the right real C# function that will actually process the condition. Therefore, depending on the function result, decide where to point to execute my Response function.
Furthermore: This is just the kind example, because there are functions as * that represent something like: "any condition is true" what in almost all cases this function is the last in the chain (the default function).
That's my problem, I can't realize what is the easiest way to cope with this problem.
Maybe a chain of delegates? Lambdas? Anonymous stored into a structure...
Could you give me your measure/advise? Where to start?
Depending on the level of extensibility you want to have, I would say the most extensible way would be to use reflection to get method references, after you have parsed the input string.
You can start by splitting your problem into smaller subproblems.
Let's say you are aiming for something like this:
static void Main(string[] args)
{
string rules =
"Check(Morning):Say(Good morning)|" +
"Check(Afternoon):Say(Good afternoon)|" +
"Check(Evening):Say(Good night)";
// next, you need some **object instances** which will
// provide a context for your "test" and "action" methods.
// you don't want to use static methods if you
// went through the pain of defining such an architecture!
// let's say that a "Tester" object has a "Check" method,
// and an "Executor" object has a "Say" method:
var tester = new Tester("Afternoon");
var executor = new Executor();
// since I suck at regular expressions,
// I am using plain string methods to split
// the expression into tokens. You might want
// to add some validation
foreach (var rule in rules.Split('|'))
{
var result = Parse(rule, tester, executor);
if (result.TestPassed)
{
result.Execute();
break;
}
}
}
A "result" as it's used above would then have an interface like this:
public interface IResult
{
// returns true if a test is fulfilled
bool TestPassed { get; }
// executes the related action
void Execute();
}
And, if you want to delegate actual actions to some unknown methods, a reasonable way to implement it would be something like this:
public class Result : IResult
{
#region IResult Members
private readonly Func<bool> _testMethod;
public bool TestPassed
{
get { return _testMethod(); }
}
private readonly Action _actionMethod;
public void Execute()
{
_actionMethod();
}
#endregion
public Result(Func<bool> testMethod, Action actionMethod)
{
_testMethod = testMethod;
_actionMethod = actionMethod;
}
}
What's left is to use some reflection to get the actual methods out of your strings:
private static IResult Parse(string rule, object tester, object executor)
{
// split into test/action
var tokens = rule.Split(':');
// extract the method/parameter part for each expression
var test = GetMethodAndParams(tokens[0]);
var action = GetMethodAndParams(tokens[1]);
// use reflection to find actual methods
var testMethod = tester.GetType().GetMethod(test.Method);
var actionMethod = executor.GetType().GetMethod(action.Method);
// return delegates which will simply invoke these methods
return new Result
(
() => (bool)testMethod.Invoke(tester, new object[] { test.Param }),
() => actionMethod.Invoke(executor, new object[] { action.Param })
);
}
That is, more or less, your program's skeleton. You should be able to fill in the missing parts yourself, as an exercise. If you have problems, I can update the answer later.
A GetMethodAndParams method should split the input string into a Tuple (or your custom class) which contains the method name and its params as plain strings. Tester and Executor classes can also be implemented trivially.
It looks like you want a pattern along the lines of the .NET TryParse() methods. In that case, you would modify your check method to have an out parameter that is the value (represented in your example by #).
int result;
if(Check('Value', out result))
ShowImage(result);
else(Check('Value2', out result))
OtherFunction(result);
Finally I'm back here to post what I've done few weeks ago to solve this situation.
It was easy.
Regex class provide few options, one of those is "Explicit Catpure", all streams with the form (?) can be handled as strong typed parameters so, if the named group "IsNotEmptyorNull" then the function is present and it is promotable to casting using the form Enum.Parse("").
Snipet:
Regex rx = new Regex(#"(?<function>Check|BooleanOp)\('(?<param>[\w]+)'\){1}:(?<action>[\w]+){1}", RegexOptions.ExplicitCapture);
Match m;
Dictionary<FunctionArray, String> actions = new Dictionary<FunctionArray, String>();
if((m=rx.Match(strStream)).Success)
{
actions.Add((FunctionArray)Enum.Parse(typeof(FunctionArray), m.Groups["function"].value, true), m.Groups["param"].value);
}
Of course, there are lost the action part so I've improved the Dictionary stuff with an specialized Struct that can handle the functions and values as a source for decision taking.
Thanks to all. Ed.

Categories