Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
epswing
Nov 4, 2003

Soiled Meat
If one wanted to create a multi-user LOB application, with a central server and windows desktop clients, which .NET tools would you use these days?

Adbot
ADBOT LOVES YOU

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

epalm posted:

If one wanted to create a multi-user LOB application, with a central server and windows desktop clients, which .NET tools would you use these days?

An HTTP API for the server, ASP.NET Core. Because I'd give it a 95% chance that you'll be asked to make a web or non-Windows client within five years, so it's not worth it to use anything else. Use OpenAPI to autogenerate a .NET client from a server, or a client and a server stub from a spec. Make the autogeneration part of your CI.

Keep the API server fully stateless and run job queues and assorted services in a separate process accessing the same data store.

For the desktop client, currently WPF, but I'd be keeping a real close eye on the Xamarin.Forms previews that can run on desktop (WPF and GTK# backends).

F# on both sides, because data integrity and catching corner cases is king in LOB apps, and once you're past the initial onboarding process F# has the better tools for that.

mystes
May 31, 2006

epalm posted:

If one wanted to create a multi-user LOB application, with a central server and windows desktop clients, which .NET tools would you use these days?
I think in 2019 even if you're only targeting windows desktop clients, you're going to want to at least make the server be a REST api exactly like you would for an SPA (so in the case of .net I guess ASP.NET Core MVC) and then you can just make a desktop client that calls the API appropriately if necessary.

Or just use electron or something for the client anyway even though the clients are all running windows.

Mr Shiny Pants
Nov 12, 2012

NihilCredo posted:

An HTTP API for the server, ASP.NET Core. Because I'd give it a 95% chance that you'll be asked to make a web or non-Windows client within five years, so it's not worth it to use anything else. Use OpenAPI to autogenerate a .NET client from a server, or a client and a server stub from a spec. Make the autogeneration part of your CI.

Keep the API server fully stateless and run job queues and assorted services in a separate process accessing the same data store.

For the desktop client, currently WPF, but I'd be keeping a real close eye on the Xamarin.Forms previews that can run on desktop (WPF and GTK# backends).

F# on both sides, because data integrity and catching corner cases is king in LOB apps, and once you're past the initial onboarding process F# has the better tools for that.

I'll second this.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

NihilCredo posted:

An HTTP API for the server, ASP.NET Core. Because I'd give it a 95% chance that you'll be asked to make a web or non-Windows client within five years, so it's not worth it to use anything else. Use OpenAPI to autogenerate a .NET client from a server, or a client and a server stub from a spec. Make the autogeneration part of your CI.

Keep the API server fully stateless and run job queues and assorted services in a separate process accessing the same data store.

For the desktop client, currently WPF, but I'd be keeping a real close eye on the Xamarin.Forms previews that can run on desktop (WPF and GTK# backends).

F# on both sides, because data integrity and catching corner cases is king in LOB apps, and once you're past the initial onboarding process F# has the better tools for that.

I'm thirding this and also seconding electron. I'd need a really, really, really good business case to build something that wasn't immediately portable to the web in 2019. And even then, they're probably wrong.

epswing
Nov 4, 2003

Soiled Meat
And what would you use to allow the central server communicate with the clients? I.e. I save a record over here, I want all other clients to see the change, without polling. MSMQ? SignalR? Something else?

NihilCredo posted:

An HTTP API for the server, ASP.NET Core. Because I'd give it a 95% chance that you'll be asked to make a web or non-Windows client within five years, so it's not worth it to use anything else. Use OpenAPI to autogenerate a .NET client from a server, or a client and a server stub from a spec. Make the autogeneration part of your CI.

Assuming Windows, where does ASP.NET Core run? IIS? Hostable Web Core? Something else?

NihilCredo posted:

Keep the API server fully stateless and run job queues and assorted services in a separate process accessing the same data store.

Assuming Windows, where does the separate "job queue" process run? Windows Service? Something else?

epswing fucked around with this message at 16:53 on May 16, 2019

B-Nasty
May 25, 2005

epalm posted:

Assuming Windows, where does ASP.NET Core run? IIS? Hostable Web Core? Something else?

IIS In-Process (Core >=2.2) is your best option here. Especially now that MS reversed their stupid decision to use Kestrel and a hacky reverse proxy.

epalm posted:

Assuming Windows, where does the separate "job queue" process run? Windows Service? Something else?

Windows Service is still the best option now with the Windows Compatibility Pack. Win Services have a small learning curve, but they're pretty simple and powerful. There was never any need for garbage like TopShelf, which over-complicates a pretty simple model.

I'm a big proponent of using Azure Service Bus for your queue needs. It's dirt cheap, and has a ton of nice features and a easy Nuget package library to use it. MSMQ is probably not going to be supported in Core, and it's old, hard-to-administer, and full of footguns.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



epalm posted:

MSMQ? SignalR? Something else?

Having used MSMQ and RabbitMQ at the same job, I'd say stay away from MSMQ and consider Rabbit.

B-Nasty
May 25, 2005


Also a very good option if you need/want to manage your own messaging/queue infrastructure.

I'd still recommend AzureSB in cases where using cloud stuff is allowed. The basic level should cost you less than a few dollars a month, and the 'standard' level is about $10/month (assuming always on) and includes topics and other advanced functionality. Self-hosting Rabbit with redundancy may end up costing more in time+hardware costs.

Mr Shiny Pants
Nov 12, 2012

epalm posted:

And what would you use to allow the central server communicate with the clients? I.e. I save a record over here, I want all other clients to see the change, without polling. MSMQ? SignalR? Something else?


Assuming Windows, where does ASP.NET Core run? IIS? Hostable Web Core? Something else?


Assuming Windows, where does the separate "job queue" process run? Windows Service? Something else?

You could use websockets for the pushing of data to the clients without polling. Kafka would also be an option.

ASP.Net could run on kestrel with a reverse proxy in front. Or you could use kerstrel on IIS. Or Giraffe or Suave if you want use F#.

For the jobqueue you could use a Windows service or just a regular process that runs on the server. Loads of options really.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

B-Nasty posted:

Windows Service is still the best option now with the Windows Compatibility Pack. Win Services have a small learning curve, but they're pretty simple and powerful. There was never any need for garbage like TopShelf, which over-complicates a pretty simple model.

Azure Function is also a cromulent option if you want to go in a stateless microservice direction. You get servicebus triggers, auto-scaling, etc without having to reinvent the wheel.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

epalm posted:

And what would you use to allow the central server communicate with the clients? I.e. I save a record over here, I want all other clients to see the change, without polling. MSMQ? SignalR? Something else?

SignalR over websockets is probably a better choice than plain WSs. It has an official Typescript library anyway so it doesn't restrict your future inevitable web move. It also acts as a wrapper over some of websockets' more dangerous quirks.

Message queues exist to not lose messages, not to push them. You may or may not need them (fart popups no, price changes yes), and use them with or without a push library like SignalR.

quote:

Assuming Windows, where does ASP.NET Core run? IIS? Hostable Web Core? Something else?

Assuming Windows, where does the separate "job queue" process run? Windows Service? Something else?

The real answer here is 'whatever the guy who may need to answer the phone at 2AM because the server is down knows best'.

As a developer, I push for Docker whenever possible because it makes the deployment story super easy, and there's plenty of monitoring / healthcheck type tools to make the people in charge of operations happy as well (even without going full retard with orchestration and whatnot). But if my boss, a dyed-in-the-wool Windows dude, told me that this was a small project and he'd be the one answering 2 AM calls, I'd probably hand him a powershell to start the ASP.NET Core app as a Windows service so he can janitor it as he likes.

No Safe Word
Feb 26, 2005

B-Nasty posted:

I'd still recommend AzureSB in cases where using cloud stuff is allowed. The basic level should cost you less than a few dollars a month, and the 'standard' level is about $10/month (assuming always on) and includes topics and other advanced functionality. Self-hosting Rabbit with redundancy may end up costing more in time+hardware costs.


Of all the Azure infrastructure pieces I use at work, Service Bus is probably the best of them (Cosmos DB is pretty good too, in spite of its stupid name). Would definitely concur with this. The one thing that is moderately lacking is official tooling for it, though you can do simple stuff in the Azure Portal, and the third party Azure SB Explorer is good enough to do all we need.

B-Nasty
May 25, 2005

New Yorp New Yorp posted:

Azure Function is also a cromulent option if you want to go in a stateless microservice direction. You get servicebus triggers, auto-scaling, etc without having to reinvent the wheel.

I know the official Microsoft party line is that they've greatly improved speed, but have you found this to be true?

I did some basic testing with Azure Functions a year or so ago, and the performance was absolutely pitiful. Everything I could measure was abysmal: spin up time, execution time, etc. Running a basic VM in Azure with a Service/Console app was hundreds of times faster, and not significantly more expensive. Of course, redundancy is DIY.

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

I feel like an idiot, because this seems correct to me. JSON has no way to specify datetime types and everything is a string unless it's a number or a Boolean. It looks like JSON.net is reading in the string, parsing it as a datetime and setting it to the correct timezone. What's the problem?

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION
Oh poo poo I just reread and I did misunderstand. The above will remain as a testament to my own inability to read and parse strings, much like the library I was defending.

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION
Bit of a meta question rather than a .NET question. I'm using a CQRS pattern for a new project and I'm curious what people thinking regarding where the line should be for a command. Are commands supposed to be specifically for dealing with database mutations? For example if I want to send an email and then log it to the database, would I used some kind of communication facade to send the email AND call a command that persists the email message to the database? Or does it make sense to have the command send the email within its handler AND persist it to the database?

Obviously both would work, but I'm curious what people's opinions are around this. My instinct is telling me that commands are really just for interacting with the database not for business logic. For business logic a facade can be made that will leverage commands to perform larger units of work. Thoughts? Am I on the wrong track completely here?

Mr Shiny Pants
Nov 12, 2012
Commands update state in your aggregates ( this could mean a DB, but it does not have to be ), sending an email sounds like something that happens because of a trigger somewhere else.

Sending an email sounds to me like something that happens because of a previous command has updated the state of some entity and it needing to tell the world about it. The command could be sendPasswordResetEmail, it updates the entity in the aggregate ( a security principal perhaps? ) with a flag that it needs to send an email and stores the command as sentPasswordResetEmail. It updates the readmodel with this flag and there might be a job system that runs on these tables sending every person an email where the flag is set and storing the email somewhere and issuing a new command to the aggregate that it has done so. This has the added benefit, if you use something like eventsourcing, that you can replay the commands without actually sending the emails ( disable the job system when rebuilding the aggregates, otherwise people might receive the email again).

Before the command does its stuff it should have been validated by your business rules ( is every field filled in etc. etc. ).

All IMHO of course.

Mr Shiny Pants fucked around with this message at 07:40 on May 21, 2019

EssOEss
Oct 23, 2006
128-bit approved

B-Nasty posted:

Especially now that MS reversed their stupid decision to use Kestrel and a hacky reverse proxy.

Oh huh what happened now?

ThePeavstenator
Dec 18, 2012

:burger::burger::burger::burger::burger:

Establish the Buns

:burger::burger::burger::burger::burger:

EssOEss posted:

Oh huh what happened now?

You can host .NET Core 2.2+ apps in-process on IIS itself instead of the .NET Core app running on a Kestrel host with IIS acting as a proxy forwarding requests to it.

When I say "you can" I mean "you should" unless you've got multiple .NET Core apps running behind a single IIS proxy (you should not do this).

mst4k
Apr 18, 2003

budlitemolaram


I cannot say enough good things about NServiceBus. It's amazing.

Macichne Leainig
Jul 26, 2012

by VG

karma_coma posted:

I cannot say enough good things about NServiceBus. It's amazing.

Is this because you used RMQ in the past and it sucks? Just curious. I've had less than stellar experiences with RMQ in the past myself but everything else I found was much worse in some regard.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Protocol7 posted:

Is this because you used RMQ in the past and it sucks? Just curious. I've had less than stellar experiences with RMQ in the past myself but everything else I found was much worse in some regard.

NServiceBus isn't just another message queue, it's more a library implementing message bus patterns, and you can use RabbitMQ as the transport (or kafka/ msmq/ whatever). If you just use the .NET rabbitmq driver you're probably just going to end up with your own lovely version of nservicebus anyway.

FormatAmerica
Jun 3, 2005
Grimey Drawer
Ever use MassTransit, if so any thoughts on how they compare?

Macichne Leainig
Jul 26, 2012

by VG

Bruegels Fuckbooks posted:

NServiceBus isn't just another message queue, it's more a library implementing message bus patterns, and you can use RabbitMQ as the transport (or kafka/ msmq/ whatever). If you just use the .NET rabbitmq driver you're probably just going to end up with your own lovely version of nservicebus anyway.

Yeah, my experience with it was definitely using it just as a message bus, so that makes sense. I don’t work at that company anymore so I can’t make any recommendations but now I know for next time.

LongSack
Jan 17, 2003

I am trying to do ASP.NET core web site that will run on Linux (specifically, Centos). People say to use Docker. So I installed Docker on my server, no problem. Then I go to install Docker Desktop on my development machine (Windows 10) and I see that it requires Hyper-V. I can't enable Hyper-V because I need to run VMWare Workstation for work.

So is there a good way to deploy a Docker container without having Docker Desktop? Like do my development using Chrome or whatever, and when I'm ready to publish somehow get it into a Docker image?

If not, is there another deployment strategy / tool that is good to use?

TIA

necrotic
Aug 2, 2005
I owe my brother big time for this!
You could run docker in a linux VM instead, with a mount pointing at your project. The only other,
option, to work on docker locally, is to flip between Hyper-V and VMWare with a reboot.

You could also use CI to build the image on commits/certain tag patterns. There are tons of options for that.

Nevett
Aug 31, 2001

LongSack posted:

I am trying to do ASP.NET core web site that will run on Linux (specifically, Centos). People say to use Docker. So I installed Docker on my server, no problem. Then I go to install Docker Desktop on my development machine (Windows 10) and I see that it requires Hyper-V. I can't enable Hyper-V because I need to run VMWare Workstation for work.

So is there a good way to deploy a Docker container without having Docker Desktop? Like do my development using Chrome or whatever, and when I'm ready to publish somehow get it into a Docker image?

If not, is there another deployment strategy / tool that is good to use?

TIA

You can try getting Docker running via VMWare, some searching revealed https://medium.com/@ans_ashkan/how-to-use-docker-on-windows-using-vmware-workstation-without-hyper-v-83b3449fe07d

Otherwise you could not worry about using Docker in local development, and just produce an image for production deployment as part of a CI pipeline using a service like CircleCI, AppVeyor, etc
https://circleci.com/blog/how-to-build-a-docker-image-on-circleci-2-0/

The latter is something you'd probably want to set up on any sizable project regardless of your development environment.

E:F,B

LongSack
Jan 17, 2003

Thanks! I'm not close to deployment yet, but i'll check those links out.

Another question: Both of the books I'm using for reference refer to Bower for client-side library management. Bower is dead and gone, so I tried to install Bootstrap with the NuGet Package Manager using the "Install-Package bootstrap" command. It appeared to work (i.e, the NuGet Dependencies have references to bootstrap, jquery and popper), but it didn't actually copy the libraries anywhere. So what exactly did it do?

Note that I found the "Add -> Client-Side Library" menu option and was able to install bootstrap locally using that, but I still have no idea what the NuGet Package Manager did or thinks it did. When I use it for desktop apps, it copies the libraries locally.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt


I would try this first, and if it doesn't work, you can install the old Docker Toolbox which runs on Virtualbox instead of Hyper-V. It's obsolete but still works quite fine for development.

If you're on the Insiders release schedule, a month from now you'll be able to install the first builds of WSL 2 which will support Docker.

Mr Shiny Pants
Nov 12, 2012

LongSack posted:

Thanks! I'm not close to deployment yet, but i'll check those links out.

Another question: Both of the books I'm using for reference refer to Bower for client-side library management. Bower is dead and gone, so I tried to install Bootstrap with the NuGet Package Manager using the "Install-Package bootstrap" command. It appeared to work (i.e, the NuGet Dependencies have references to bootstrap, jquery and popper), but it didn't actually copy the libraries anywhere. So what exactly did it do?

Note that I found the "Add -> Client-Side Library" menu option and was able to install bootstrap locally using that, but I still have no idea what the NuGet Package Manager did or thinks it did. When I use it for desktop apps, it copies the libraries locally.

If you use VS Code you can use the docker extension and connect to a remote Docker host. This way you don't need a local Docker daemon.

roadhead
Dec 25, 2001

I need to know what PDF library will let me easily generate my own PDFs in .NET (mostly just compositing a few images and adding some text regions, though later I'll want to combine multiple existing single page PDFs into one big one...)


UI Project is Framework 4.7 (WPF) and my Model is Core 2.0 - so obviously native C# solutions preferred :)

IronPDF had the best looking web site, but this iTextSharp NuGet package has the most downloads, though PDFsharp isn't far behind it...

ugh I wish It was easier to see licensing information from the NuGet manager.

necrotic
Aug 2, 2005
I owe my brother big time for this!

NihilCredo posted:

I would try this first, and if it doesn't work, you can install the old Docker Toolbox which runs on Virtualbox instead of Hyper-V. It's obsolete but still works quite fine for development.

If you're on the Insiders release schedule, a month from now you'll be able to install the first builds of WSL 2 which will support Docker.

WSL 1 and 2 require Hyper-V.

edit: maybe 1 doesn't, but 2 does.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

roadhead posted:

I need to know what PDF library will let me easily generate my own PDFs in .NET (mostly just compositing a few images and adding some text regions, though later I'll want to combine multiple existing single page PDFs into one big one...)


UI Project is Framework 4.7 (WPF) and my Model is Core 2.0 - so obviously native C# solutions preferred :)

IronPDF had the best looking web site, but this iTextSharp NuGet package has the most downloads, though PDFsharp isn't far behind it...

ugh I wish It was easier to see licensing information from the NuGet manager.

Does it have to be free, or are paid-for products acceptable?

We use DynamicPDF for some stuff at work and it's ok for what we do, but it costs money. No idea whether they've released it as .NET Standard/.NET Core, and I haven't tried anything else for comparison.

roadhead
Dec 25, 2001

Hammerite posted:

Does it have to be free, or are paid-for products acceptable?

We use DynamicPDF for some stuff at work and it's ok for what we do, but it costs money. No idea whether they've released it as .NET Standard/.NET Core, and I haven't tried anything else for comparison.

Free isn't a requirement, but it does need to SHIP in my software that people install on their machines, so I'd have better luck getting approval for something that has a one time cost instead of a licensing model where we have to pay per instance.

Alan G
Dec 27, 2003
I’ve used Ibex to generate PDFs. Its libraries are .Net Framework and there’s a prototype in .Net Core available now. https://www.xmlpdf.com you write in xsl-fo and then use xslt to transform into pdfs. So a bit different to writing the document in c# against a library but you can ship the libraries with your application. The support is pretty incredible though. I was working on upgrading our version to one where they changed their svg engine and was submitting bug reports and they’d deploy a fix within 24hrs most of the time.

Scaramouche
Mar 26, 2001

SPACE FACE! SPACE FACE!

I've used PDFsharp in the past but have no idea how well it's aged into the -core era.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

roadhead posted:

Free isn't a requirement, but it does need to SHIP in my software that people install on their machines, so I'd have better luck getting approval for something that has a one time cost instead of a licensing model where we have to pay per instance.

???

It is a one-time cost, as far as I understand it. You buy one of the "developer" licenses and you can develop applications with it and distribute them without requiring the end user to purchase licenses. If it doesn't work like that then my company is doing it wrong (!)

ljw1004
Jan 18, 2005

rum
Somehow, every single PDF library I looked at was janky in one way or another. I ended up just writing my own PDFs. The PDF file format is easy, and it worked out quicker for me to figure out how to construct the PDF than it was to learn an idiosyncratic PDF library.

(This approach seems fine for simple things like positioned text and lines. Once you start wanting to freely flow paragraphs or draw complicated graphics, then I'm sure a fancier PDF library will be necessary).

code:
Module Module1

    Sub Main()

        Using file As New IO.FileStream("a.pdf", IO.FileMode.Create),
            writer As New IO.StreamWriter(file, Text.Encoding.ASCII)
            Dim xrefs As New List(Of Long)()

            ' Header
            writer.WriteLine("%PDF-1.2")

            ' Body: comment with binary contents, so everyone recognizes the file as binary
            writer.Write("%") : writer.Flush()
            file.Write({&HC7, &HEC, &H8F, &HA2}, 0, 4) : file.Flush()
            writer.WriteLine("")

            ' Body: catalog
            writer.Flush() : file.Flush() : xrefs.Add(file.Position)
            writer.WriteLine("1 0 obj")
            writer.WriteLine("<<")
            writer.WriteLine("  /Type /Catalog")
            writer.WriteLine("  /Pages 2 0 R")
            writer.WriteLine(">>")
            writer.WriteLine("endobj")

            ' Body: page-list
            writer.Flush() : file.Flush() : xrefs.Add(file.Position)
            writer.WriteLine("2 0 obj")
            writer.WriteLine("<<")
            writer.WriteLine("  /Type /Pages")
            writer.WriteLine("  /Kids [3 0 R]")
            writer.WriteLine("  /Count 1")
            writer.WriteLine(">>")
            writer.WriteLine("endobj")

            ' Body: page1
            writer.Flush() : file.Flush() : xrefs.Add(file.Position)
            writer.WriteLine("3 0 obj")
            writer.WriteLine("<<")
            writer.WriteLine("  /Type /Page")
            writer.WriteLine("  /Parent 2 0 R")
            writer.WriteLine("  /MediaBox [0 0 612 792]") ' Default userspace units: 72/inch, origin at bottom left
            writer.WriteLine("  /Resources")
            writer.WriteLine("  <<")
            writer.WriteLine("    /ProcSet [/PDF/Text]")
            writer.WriteLine("    /Font")
            writer.WriteLine("    <<")
            writer.WriteLine("      /F0 4 0 R")
            writer.WriteLine("      /F1 5 0 R")
            writer.WriteLine("      /F2 6 0 R")
            writer.WriteLine("    >>")
            writer.WriteLine("  >>")
            writer.WriteLine("  /Contents 7 0 R")
            writer.WriteLine(">>")
            writer.WriteLine("endobj")

            ' Body: fonts
            writer.Flush() : file.Flush() : xrefs.Add(file.Position)
            writer.WriteLine("4 0 obj")
            writer.WriteLine("<<")
            writer.WriteLine("  /Type /Font")
            writer.WriteLine("  /Subtype /Type1")
            writer.WriteLine("  /Encoding /WinAnsiEncoding")
            writer.WriteLine("  /BaseFont /Times-Roman")
            writer.WriteLine(">>")
            writer.Flush() : file.Flush() : xrefs.Add(file.Position)
            writer.WriteLine("5 0 obj")
            writer.WriteLine("<<")
            writer.WriteLine("  /Type /Font")
            writer.WriteLine("  /Subtype /Type1")
            writer.WriteLine("  /Encoding /WinAnsiEncoding")
            writer.WriteLine("  /BaseFont /Times-Bold")
            writer.WriteLine(">>")
            writer.Flush() : file.Flush() : xrefs.Add(file.Position)
            writer.WriteLine("6 0 obj")
            writer.WriteLine("<<")
            writer.WriteLine("  /Type /Font")
            writer.WriteLine("  /Subtype /Type1")
            writer.WriteLine("  /Encoding /WinAnsiEncoding")
            writer.WriteLine("  /BaseFont /Times-Italic")
            writer.WriteLine(">>")

            ' Body: page1 contents
            writer.Flush() : file.Flush() : xrefs.Add(file.Position)
            Dim sb As New Text.StringBuilder
            sb.AppendLine("BT")             ' BT = begin text object, with text-units the same as userspace-units
            sb.AppendLine("/F0 40 Tf")      ' Tf = start using the named font "F0" with size "40"
            sb.AppendLine("40 TL")          ' TL = set line height to "40"
            sb.AppendLine("230.0 400.0 Td") ' Td = position text point at coordinates "230.0", "400.0"
            sb.AppendLine("(Hello all) '")  ' Apostrophe = print the text, and advance to the next line
            sb.AppendLine("/F2 20 Tf")      '
            sb.AppendLine("20 TL")          '
            sb.AppendLine("0.0 0.2 1.0 rg") ' rg = set fill color to RGB("0.0", "0.2", "1.0")
            sb.AppendLine("(ol" & enc("é") & ") '")
            sb.AppendLine("ET")             '
            '
            writer.WriteLine("7 0 obj")
            writer.WriteLine("<<")
            writer.WriteLine("  /Length " & sb.Length)
            writer.WriteLine(">>")
            writer.WriteLine("stream")
            writer.Write(sb.ToString())
            writer.WriteLine("endstream")
            writer.WriteLine("endobj")

            ' Cross-reference section
            writer.Flush() : file.Flush() : Dim xref_pos = file.Position
            writer.WriteLine("xref")
            writer.WriteLine("1 " & xrefs.Count)
            For Each xref In xrefs
                writer.WriteLine("{0:0000000000} {1:00000} n", xref, 0)
            Next

            ' Trailer
            writer.WriteLine("trailer")
            writer.WriteLine("<<")
            writer.WriteLine("  /Size " & xrefs.Count)
            writer.WriteLine("  /Root 1 0 R")
            writer.WriteLine(">>")
            writer.WriteLine("startxref")
            writer.WriteLine(xref_pos)
            writer.WriteLine("%%EOF")
        End Using

        Process.Start("a.pdf")

    End Sub


    ' WinAnsiEncoding, in octal
    Dim enc = New Dictionary(Of String, String) From {
        {"A", "\101"}, {"Æ", "\306"}, {"Á", "\301"}, {"Â", "\302"}, {"Ä", "\304"}, {"À", "\300"}, {"Å", "\305"},
        {"Ã", "\303"}, {"B", "\102"}, {"C", "\103"}, {"Ç", "\307"}, {"D", "\104"}, {"E", "\105"}, {"É", "\311"},
        {"Ê", "\312"}, {"Ë", "\313"}, {"È", "\310"}, {"Ð", "\320"}, {"F", "\106"}, {"G", "\107"}, {"H", "\110"},
        {"I", "\111"}, {"Í", "\315"}, {"Î", "\316"}, {"Ï", "\317"}, {"Ì", "\314"}, {"J", "\112"}, {"K", "\113"},
        {"L", "\114"}, {"M", "\115"}, {"N", "\116"}, {"Ñ", "\321"}, {"O", "\117"}, {"Œ", "\214"}, {"Ó", "\323"},
        {"Ô", "\324"}, {"Ö", "\326"}, {"Ò", "\322"}, {"Ø", "\330"}, {"Õ", "\325"}, {"P", "\120"}, {"Q", "\121"},
        {"R", "\122"}, {"S", "\123"}, {"Š", "\212"}, {"T", "\124"}, {"Þ", "\336"}, {"U", "\125"}, {"Ú", "\332"},
        {"Û", "\333"}, {"Ü", "\334"}, {"Ù", "\331"}, {"V", "\126"}, {"W", "\127"}, {"X", "\130"}, {"Y", "\131"},
        {"Ý", "\335"}, {"Ÿ", "\237"}, {"Z", "\132"}, {"a", "\141"}, {"á", "\341"}, {"â", "\342"}, {"´", "\264"},
        {"ä", "\344"}, {"æ", "\346"}, {"à", "\340"}, {"&", "\046"}, {"å", "\345"}, {"^", "\136"}, {"~", "\176"},
        {"*", "\052"}, {"@", "\100"}, {"ã", "\343"}, {"b", "\142"}, {"\", "\134"}, {"|", "\174"}, {"{", "\173"},
        {"}", "\175"}, {"[", "\133"}, {"]", "\135"}, {"•", "\225"}, {"c", "\143"}, {"ç", "\347"}, {"¸", "\270"},
        {"¢", "\242"}, {"ˆ", "\210"}, {":", "\072"}, {",", "\054"}, {"©", "\251"}, {"¤", "\244"}, {"d", "\144"},
        {"†", "\206"}, {"‡", "\207"}, {"°", "\260"}, {"¨", "\250"}, {"÷", "\367"}, {"$", "\044"}, {"e", "\145"},
        {"é", "\351"}, {"ê", "\352"}, {"ë", "\353"}, {"è", "\350"}, {"8", "\070"}, {"…", "\205"}, {"—", "\227"},
        {"–", "\226"}, {"=", "\075"}, {"ð", "\360"}, {"!", "\041"}, {"¡", "\241"}, {"f", "\146"}, {"5", "\065"},
        {"ƒ", "\203"}, {"4", "\064"}, {"g", "\147"}, {"ß", "\337"}, {"`", "\140"}, {">", "\076"}, {"«", "\253"},
        {"»", "\273"}, {"‹", "\213"}, {"›", "\233"}, {"h", "\150"}, {"-", "\055"}, {"i", "\151"}, {"í", "\355"},
        {"î", "\356"}, {"ï", "\357"}, {"ì", "\354"}, {"j", "\152"}, {"k", "\153"}, {"l", "\154"}, {"<", "\074"},
        {"¬", "\254"}, {"m", "\155"}, {"¯", "\257"}, {"µ", "\265"}, {"&#8719;", "\327"}, {"n", "\156"}, {"9", "\071"},
        {"ñ", "\361"}, {"#", "\043"}, {"o", "\157"}, {"ó", "\363"}, {"ô", "\364"}, {"ö", "\366"}, {"œ", "\234"},
        {"ò", "\362"}, {"1", "\061"}, {"½", "\275"}, {"¼", "\274"}, {"¹", "\271"}, {"ª", "\252"}, {"º", "\272"},
        {"ø", "\370"}, {"õ", "\365"}, {"p", "\160"}, {"¶", "\266"}, {"(", "\050"}, {")", "\051"}, {"%", "\045"},
        {".", "\056"}, {"·", "\267"}, {"‰", "\211"}, {"+", "\053"}, {"±", "\261"}, {"q", "\161"}, {"?", "\077"},
        {"¿", "\277"}, {"""", "\042"}, {"„", "\204"}, {ChrW(8220), "\223"}, {ChrW(8221), "\224"}, {"‘", "\221"},
        {"’", "\222"}, {"‚", "\202"}, {"'", "\047"}, {"r", "\162"}, {"®", "\256"}, {"&#730;", "\260"}, {"s", "\163"},
        {"š", "\232"}, {"§", "\247"}, {";", "\073"}, {"7", "\067"}, {"6", "\066"}, {"/", "\057"}, {" ", "\040"},
        {"£", "\243"}, {"t", "\164"}, {"þ", "\376"}, {"3", "\063"}, {"¾", "\276"}, {"³", "\263"}, {"˜", "\230"},
        {"™", "\231"}, {"2", "\062"}, {"²", "\262"}, {"u", "\165"}, {"ú", "\372"}, {"û", "\373"}, {"ü", "\374"},
        {"ù", "\371"}, {"_", "\137"}, {"v", "\166"}, {"w", "\167"}, {"x", "\170"}, {"y", "\171"}, {"ý", "\375"},
        {"ÿ", "\377"}, {"¥", "\245"}, {"z", "\172"}, {"0", "\060"}}

End Module

Adbot
ADBOT LOVES YOU

nielsm
Jun 1, 2009



DI question, I'm using SimpleInjector to set up my application. Now I need to have a dynamic configuration, depending on a configuration setting I'd like to supply a different object for a specific interface. I think.
I'd like to have an IUserIdentitySupplicant, usually fulfilled by an AutoDetectIdentitySupplicant, but the installer should be able to set a setting that would select a FixedIdentitySupplicant that doesn't dynamically detect and supply identity data, just having a static result.

Does this sound like the right approach, and what would be the pattern to implement this?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply