Let's say I have a table called Couriers in my database and an Entity Framework class also called Couriers (DbContext.Couriers), with this example data:
Id: 1. Name: UPS
Id: 2. Name: DHL
I have extended this class with two subclasess CourierUPS and CourierDHL, and both two have a new method called PrintSticker(), which is different in UPS and DHL (each company needs a different sticker format).
I also have a view with a combo to select between UPS or DHL and a button that calls the PrintSticker method of the selected Courier.
Well, the problem is that I can create the object with an IF statement (if selectedCourier = "UPS" create new CourierUPS elseif selectedCourier = "DLH" create new CourierDHL... it's just pseudo code), but it is not a good way, because if I want to create FedEx courier in the future, I will need to change that IF statement, so I think I will become a mess.
What I want to achieve is a way to dinamycally obtain this:
C#
CourierUPS courier = new CourierUPS;
VB.NET
Dim courier as CourierUPS = new CourierUPS
The questions are:
1) Is there a simple way to save the name of the class in the table (CourierUPS, CourierDHL, etc.), and use it the code to create the new objects?
2) Is there a simple way to dynamically construct the name of the class, attaching the name of the courier (DHL or UPS) to the "Courier" word? Courier + UPS = CourierUPS, so our code will use that class.
Both C# or VB.NET solutions would be appreciatted.
Thank you
And option that you can try is to create a factory dictionary for creating each type.
Start out with this:
var factory = new Dictionary<string, Func<Courier>>()
{
{ "UPS", () => new CourierUPS() },
{ "DHL", () => new CourierDHL() },
};
Now you can create either the "UPS" or "DHL" courier like this:
var courier = factory["UPS"].Invoke();
But, if you now want to configure a new courier you can pass your dictionary into a method that can add in "FedEx", and you can add it like so:
factory["FedEx"] = () => new CourierFedEx();
Now you can do this back in your main code:
var courier = factory["FedEx"].Invoke();
It's basic, but it works.
Related
I am trying to set default price list for a product bundle that i am trying to create using Microsoft.CrmSdk.CoreAssemblies. I have written the working code that successfully creates the product bundle with all the configurations that I specify in the code but default price list is never set. Following is the code snippet:
Entity ProductBundleEntity = new Entity("product");
ProductBundleEntity.Attributes["name"] = Name;
ProductBundleEntity.Attributes["productstructure"] = new OptionSetValue(3);
ProductBundleEntity.Attributes["productnumber"] = Guid.NewGuid().ToString();
///// setting defult price list here
ProductBundleEntity.Attributes["pricelevelid"] = new EntityReference("pricelevel", PriceListID);
ProductBundleEntity.Attributes["defaultuomscheduleid"] = new EntityReference("uomschedule", UOMScheduleID);
ProductBundleEntity.Attributes["defaultuomid"] = new EntityReference("uom", UOMID);
Please suggest if i am missing anything.
Did you receive any error?
When is your plugin running, create/update?
Is it synchronous? –
is it pre operation or post?
If post you might have to use service.update(Entity object) Better try with pre operation so that same object/ can be used.
Although I don't know the definition of the PriceListId variable, normally you need to assign an id as below, I think the PriceListId variable does not contain a value;
ProductBundleEntity.Attributes["pricelevelid"] = new EntityReference("pricelevel", ((Microsoft.Xrm.Sdk.EntityReference)(originalEntity.Attributes["pricelevelid"])).Id);
I work on BDD infrastructure in c# using specflow, and ReportPortal. I am using scenario outline in order to automated the same flow, with several parameters, but I want to have a dynamic title in reportPortal. an example:
Scenario Outline: Perform a Test on car <car model>
Given I have the car"<car>"
When I expect that "<car>" has 4 wheels
Then I expect that the car will be able to move
This scenario doesn't work, since Gherkin doesnt support in scenario outline dynamic title. Is there a way where I can somehow influence the scenario title in the following code:
var currentFeature = FeatureContext.Current;
var currentScenario = ScenarioContext.Current;
var jsonRootElement = (JsonReportRootObject)currentFeature["JsonReport"];
var scenarioElement = new Element();
scenarioElement.keyword = "Scenario";
scenarioElement.line = 0;
scenarioElement.name = currentScenario.ScenarioInfo.Title;
scenarioElement.steps = new List<Step>();
https://github.com/reportportal/example-net-specflow/blob/master/src/Example.SpecFlow/Hooks/Hooks1.cs
You can subscribe on ReportPortalAddin.BeforeScenarioStarted event and modify e.StartTestItemRequest.Name property.
Thanks to Dave Bennett, I have a great Neo4j query that provides the results I need. I need to get this to work in Neo4JClient. Here's my working Neo4j query:
`// Composite Tile with related users
match (t:Tile{summary:"Test 1"})<-[:ASSIGNED_TO]-(u:User)
with {summary: t.summary,
id: t.id,
sprint_id: t.sprint_id,
size: t.size,
percent_done: t.percent_done,
color: t.color_id,
description: t.description,
queue_id: t.queue_id,
swimlane_id: t.swimlane_id,
icons: t.icons,
order: t.order,
assignees: collect(u)} as tile
RETURN collect(tile) as tiles`
Visual Studio and/or Neo4jClient is not very happy with my attempt:
var compositeTile = client.Cypher
.Match("(t:Tile)<-[:ASSIGNED_TO]-(u:User)")
.Where((Tile t)=> t.summary == tile.summary)
.With( {
summary: t.summary,
id: t.id,
sprint_id: t.sprint_id,
size: t.size,
percent_done: tile.percent_done,
color: t.color,
description: t.description,
queue_id: t.queue_id,
swimlane_id: t.swimlane_id,
icons: t.icons,
Order: t.order,
assignees: collect(u)
} as tile)
.return collect(tile) as tiles;
It just throws lots of red squiggly lines, I suspect because I'm not formatting the .with statement correctly. I haven't been able to find an example, so I'm asking here. How do I do this correctly in Neo4jClient?
So, two answers to your question - the first is that the .With statement takes a string as a parameter, so you just need to wrap your text with " (or #" if you want to keep the formatting). The second answer is more of a problem for you though:
It's not possible to do what you're trying to do with Neo4jClient - at the moment it doesn't allow you to create anonymous types. It's not able to deserialize the content. I thought it might be a quick fix, but it seems like it would be more involved. So, what we're looking at here is a change of the query.
I presume you have a class called Tile with the properties you're after. So I would change the query to something like this:
client.Cypher
.Match("(t:Tile)<-[:ASSIGNED_TO]-(u:User)")
.Where((Tile t) => t.summary == tile.summary)
.Return((t,u) => new {
Tile = t.As<Tile>(),
User = u.CollectAs<User>()
});
Which will give you a C# anonymous type with a Tile and an IEnumerable<Node<User>> elements, obviously you want the Users in your Tile, so you can then parse the result:
var tiles = new List<Tile>();
foreach (var result in results)
{
var tile = result.Tile;
foreach (var user in result.Users)
tile.users.Add(user.Data);
tiles.Add(tile);
}
One thing you might find is that you need to initialize the Users collection, so either add Users = new List<User>() to your Tile constructor, or just before parsing the data.
suppose i need to send mail to customer with customer detail and his order detail.
i have template html data in a html file.customer data is there and as well as order detail is also there in same html template file. my html look like
<html>
<body>
Hi {FirstName} {LastName},
Here are your orders:
{foreach Orders}
Order ID {OrderID} Quantity : {Qty} <strong>{Price}</strong>.
{end}
</body>
</html>
now i want to fill up all sample keyword surrounded with {} with actual value and also iterate and fill up orders.
i search google and found that microsoft provide a class called MailDefinition
by which we can generate mail body dynamically. i got a sample code also like
MailDefinition md = new MailDefinition();
md.From = "test#domain.com";
md.IsBodyHtml = true;
md.Subject = "Test of MailDefinition";
ListDictionary replacements = new ListDictionary();
replacements.Add("<%Name%>", "Martin");
replacements.Add("<%Country%>", "Denmark");
string body = "
Hello <%Name%> You're from <%Country%>.";
MailMessage msg = md.CreateMailMessage("you#anywhere.com", replacements, body, new System.Web.UI.Control());
by the above code we can replace pseudo value with actual value but i don't know how iterate in Orders detail and populate orders data.
so if it is possible using MailDefinition class then please guide me with code that how can i iterate in loop and generate body for orders detail.
As an alternative to MailDefinition, have a look at RazorEngine https://github.com/Antaris/RazorEngine.
RazorEngine is a simplified templating framework built around
Microsoft's new Razor parsing engine, used in both ASP.NET MVC3 and
Web Pages. RazorEngine provides a wrapper and additional services
built around the parsing engine to allow the parsing technology to
be used in other project types.
It lets you use razor templates outside of ASP.NET MVC and then write something like this (not tested):
string template =
#"<html>
<body>
Hi #Model.FirstName #Model.LastName,
Here are your orders:
#foreach(var order in Model.Orders) {
Order ID #order.Id Quantity : #order.Qty <strong>#order.Price</strong>.
}
</body>
</html>";
var model = new OrderModel {
FirstName = "Martin",
LastName = "Whatever",
Orders = new [] {
new Order { Id = 1, Qty = 5, Price = 29.99 },
new Order { Id = 2, Qty = 1, Price = 9.99 }
}
};
string mailBody = Razor.Parse(template, model);
You can't do such "complicated" logic with the default replacement stuff (the placeholder handling is made to be used for simple variables only, e.g. names or values).
You'll have to do the parsing yourself. Depending on the complexity (e.g. loops withing loops), this can get a bit tricky.
If you don't want or need such things, it's more trivial. E.g. use the regular expression \{foreach (.*?)\}(.*?)\{end\} to find such loops, then parse the contents/matched groups the way you need. Once that part is done, you could replace other values or use the default replacement feature.
Only downside with this approach is the fact that you'll have to recreate the mail for each recipient (i.e. you can't mass mail using MailDefinition).
I am trying to find a solution, in eliminating repetitive string names, say for ex.,
in a literal field, i am populating names of the contributor of certain article's history version, and so, if "ron" has contributed to the versioning of an article 3 times, the name "ron" gets added to this literal control, and outputs "ron" 3 times.
I am trying to find, if a name is repeating twice, i should be able to populate it only one time. How can i achieve this ?
I would suggest you to use dictionary whose keys will be the author name (or the field which you don't want to be repetitive) and values will be the lists of contributors. For example,
Dictionary<string, List<Contributor>> contributors
= new Dictionary<string, List<Contributor>>();
Contributor contributor = new Contributor("ron", /*other values*/);
if ( !contributors.ContainsKey(contributor.Name) )
contributors.Add(contributor.Name,new List<Contributor>());
contributors[contributor.Name].Add(contributor);
Depending on your setup, I'd either use a StringCollection and just check if the name exists prior to insertion or just add all the names to a List and call Distinct() (extension method in System.Linq). So either:
StringCollection Names=new StringCollection();
if(!Names.Contains(Name))
Names.Add(Name);
As CharithJ suggests, or:
List<string> Names=new List<string>();
Names.Add(Name);
...
foreach(string Name in Names.Distinct())
{
...
}
Either would work well enough.
Use C#s .Contains() function to check if the name has already been added to the string
Create a model of what you want to achieve (it's like a view model) that drives the rendering of your "report". Then, the model can control this requirement of "only output each name once". Pseudo-code follows:
var ron = new Author("ron");
var ronnie = new Author("ronnie");
var report = new HistoryReport();
report.AddVersion(1, ron);
report.AddVersion(2, ron);
report.AddVersion(3, ronnie);
string renderedReport = report.Render();
// output e.g.:
// Versions 1 and 2 by ron; Version 3 by ronnie
Then you use that ouput to populate your literal control.
If you use simple string substitution, you'll mix up ron with ronnie.
StringCollection authors= new StringCollection();
if (!authors.Contains("Ron"))
{
authors.Add("Ron");
}